1console.warn(
'Scripts "build/three.js" and "build/three.min.js" are deprecated with r150+, and will be removed with r160. Please use ES Modules or alternatives: https://threejs.org/docs/index.html#manual/en/introduction/Installation' );
8 typeof exports ===
'object' && typeof module !==
'undefined' ?
factory(exports) :
9 typeof define ===
'function' && define.amd ? define([
'exports'],
factory) :
11})(
this, (
function (exports) {
'use strict';
13 const REVISION =
'160';
15 const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 };
16 const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 };
24 const VSMShadowMap = 3;
28 const TwoPassDoubleSide = 2;
38 const MinEquation = 103;
39 const MaxEquation = 104;
51 const ConstantColorFactor = 211;
52 const OneMinusConstantColorFactor = 212;
53 const ConstantAlphaFactor = 213;
54 const OneMinusConstantAlphaFactor = 214;
56 const AlwaysDepth = 1;
58 const LessEqualDepth = 3;
60 const GreaterEqualDepth = 5;
61 const GreaterDepth = 6;
62 const NotEqualDepth = 7;
66 const NoToneMapping = 0;
67 const LinearToneMapping = 1;
68 const ReinhardToneMapping = 2;
69 const CineonToneMapping = 3;
70 const ACESFilmicToneMapping = 4;
71 const CustomToneMapping = 5;
72 const AgXToneMapping = 6;
73 const AttachedBindMode =
'attached';
74 const DetachedBindMode =
'detached';
79 const EquirectangularReflectionMapping = 303;
80 const EquirectangularRefractionMapping = 304;
81 const CubeUVReflectionMapping = 306;
86 const NearestMipmapNearestFilter = 1004;
88 const NearestMipmapLinearFilter = 1005;
91 const LinearMipmapNearestFilter = 1007;
93 const LinearMipmapLinearFilter = 1008;
102 const HalfFloatType = 1016;
105 const UnsignedInt248Type = 1020;
110 const DepthFormat = 1026;
111 const DepthStencilFormat = 1027;
112 const RedFormat = 1028;
113 const RedIntegerFormat = 1029;
114 const RGFormat = 1030;
115 const RGIntegerFormat = 1031;
116 const RGBAIntegerFormat = 1033;
122 const RGB_PVRTC_4BPPV1_Format = 35840;
123 const RGB_PVRTC_2BPPV1_Format = 35841;
124 const RGBA_PVRTC_4BPPV1_Format = 35842;
125 const RGBA_PVRTC_2BPPV1_Format = 35843;
126 const RGB_ETC1_Format = 36196;
127 const RGB_ETC2_Format = 37492;
128 const RGBA_ETC2_EAC_Format = 37496;
129 const RGBA_ASTC_4x4_Format = 37808;
130 const RGBA_ASTC_5x4_Format = 37809;
131 const RGBA_ASTC_5x5_Format = 37810;
132 const RGBA_ASTC_6x5_Format = 37811;
133 const RGBA_ASTC_6x6_Format = 37812;
134 const RGBA_ASTC_8x5_Format = 37813;
135 const RGBA_ASTC_8x6_Format = 37814;
136 const RGBA_ASTC_8x8_Format = 37815;
137 const RGBA_ASTC_10x5_Format = 37816;
138 const RGBA_ASTC_10x6_Format = 37817;
139 const RGBA_ASTC_10x8_Format = 37818;
140 const RGBA_ASTC_10x10_Format = 37819;
141 const RGBA_ASTC_12x10_Format = 37820;
142 const RGBA_ASTC_12x12_Format = 37821;
143 const RGBA_BPTC_Format = 36492;
144 const RGB_BPTC_SIGNED_Format = 36494;
145 const RGB_BPTC_UNSIGNED_Format = 36495;
146 const RED_RGTC1_Format = 36283;
147 const SIGNED_RED_RGTC1_Format = 36284;
148 const RED_GREEN_RGTC2_Format = 36285;
149 const SIGNED_RED_GREEN_RGTC2_Format = 36286;
150 const LoopOnce = 2200;
151 const LoopRepeat = 2201;
152 const LoopPingPong = 2202;
153 const InterpolateDiscrete = 2300;
154 const InterpolateLinear = 2301;
155 const InterpolateSmooth = 2302;
156 const ZeroCurvatureEnding = 2400;
157 const ZeroSlopeEnding = 2401;
158 const WrapAroundEnding = 2402;
159 const NormalAnimationBlendMode = 2500;
160 const AdditiveAnimationBlendMode = 2501;
161 const TrianglesDrawMode = 0;
162 const TriangleStripDrawMode = 1;
163 const TriangleFanDrawMode = 2;
165 const LinearEncoding = 3000;
167 const sRGBEncoding = 3001;
168 const BasicDepthPacking = 3200;
169 const RGBADepthPacking = 3201;
170 const TangentSpaceNormalMap = 0;
171 const ObjectSpaceNormalMap = 1;
174 const NoColorSpace =
'';
175 const SRGBColorSpace =
'srgb';
176 const LinearSRGBColorSpace =
'srgb-linear';
177 const DisplayP3ColorSpace =
'display-p3';
178 const LinearDisplayP3ColorSpace =
'display-p3-linear';
180 const LinearTransfer =
'linear';
181 const SRGBTransfer =
'srgb';
183 const Rec709Primaries =
'rec709';
184 const P3Primaries =
'p3';
186 const ZeroStencilOp = 0;
187 const KeepStencilOp = 7680;
188 const ReplaceStencilOp = 7681;
189 const IncrementStencilOp = 7682;
190 const DecrementStencilOp = 7683;
191 const IncrementWrapStencilOp = 34055;
192 const DecrementWrapStencilOp = 34056;
193 const InvertStencilOp = 5386;
195 const NeverStencilFunc = 512;
196 const LessStencilFunc = 513;
197 const EqualStencilFunc = 514;
198 const LessEqualStencilFunc = 515;
199 const GreaterStencilFunc = 516;
200 const NotEqualStencilFunc = 517;
201 const GreaterEqualStencilFunc = 518;
202 const AlwaysStencilFunc = 519;
204 const NeverCompare = 512;
205 const LessCompare = 513;
206 const EqualCompare = 514;
207 const LessEqualCompare = 515;
208 const GreaterCompare = 516;
209 const NotEqualCompare = 517;
210 const GreaterEqualCompare = 518;
211 const AlwaysCompare = 519;
213 const StaticDrawUsage = 35044;
214 const DynamicDrawUsage = 35048;
215 const StreamDrawUsage = 35040;
216 const StaticReadUsage = 35045;
217 const DynamicReadUsage = 35049;
218 const StreamReadUsage = 35041;
219 const StaticCopyUsage = 35046;
220 const DynamicCopyUsage = 35050;
221 const StreamCopyUsage = 35042;
224 const GLSL3 =
'300 es';
226 const _SRGBAFormat = 1035;
228 const WebGLCoordinateSystem = 2000;
229 const WebGPUCoordinateSystem = 2001;
237 addEventListener( type, listener ) {
239 if ( this._listeners ===
undefined ) this._listeners = {};
241 const listeners = this._listeners;
245 listeners[ type ] = [];
249 if ( listeners[ type ].
indexOf( listener ) === - 1 ) {
251 listeners[ type ].push( listener );
257 hasEventListener( type, listener ) {
259 if ( this._listeners ===
undefined )
return false;
261 const listeners = this._listeners;
263 return listeners[ type ] !==
undefined && listeners[ type ].indexOf( listener ) !== - 1;
267 removeEventListener( type, listener ) {
269 if ( this._listeners ===
undefined )
return;
271 const listeners = this._listeners;
272 const listenerArray = listeners[ type ];
276 const index = listenerArray.indexOf( listener );
278 if ( index !== - 1 ) {
280 listenerArray.splice( index, 1 );
288 dispatchEvent( event ) {
290 if ( this._listeners ===
undefined )
return;
292 const listeners = this._listeners;
293 const listenerArray = listeners[
event.type ];
300 const array = listenerArray.slice( 0 );
302 for ( let
i = 0,
l = array.length;
i <
l;
i ++ ) {
304 array[
i ].call(
this, event );
316 const _lut = [
'00',
'01',
'02',
'03',
'04',
'05',
'06',
'07',
'08',
'09',
'0a',
'0b',
'0c',
'0d',
'0e',
'0f',
'10',
'11',
'12',
'13',
'14',
'15',
'16',
'17',
'18',
'19',
'1a',
'1b',
'1c',
'1d',
'1e',
'1f',
'20',
'21',
'22',
'23',
'24',
'25',
'26',
'27',
'28',
'29',
'2a',
'2b',
'2c',
'2d',
'2e',
'2f',
'30',
'31',
'32',
'33',
'34',
'35',
'36',
'37',
'38',
'39',
'3a',
'3b',
'3c',
'3d',
'3e',
'3f',
'40',
'41',
'42',
'43',
'44',
'45',
'46',
'47',
'48',
'49',
'4a',
'4b',
'4c',
'4d',
'4e',
'4f',
'50',
'51',
'52',
'53',
'54',
'55',
'56',
'57',
'58',
'59',
'5a',
'5b',
'5c',
'5d',
'5e',
'5f',
'60',
'61',
'62',
'63',
'64',
'65',
'66',
'67',
'68',
'69',
'6a',
'6b',
'6c',
'6d',
'6e',
'6f',
'70',
'71',
'72',
'73',
'74',
'75',
'76',
'77',
'78',
'79',
'7a',
'7b',
'7c',
'7d',
'7e',
'7f',
'80',
'81',
'82',
'83',
'84',
'85',
'86',
'87',
'88',
'89',
'8a',
'8b',
'8c',
'8d',
'8e',
'8f',
'90',
'91',
'92',
'93',
'94',
'95',
'96',
'97',
'98',
'99',
'9a',
'9b',
'9c',
'9d',
'9e',
'9f',
'a0',
'a1',
'a2',
'a3',
'a4',
'a5',
'a6',
'a7',
'a8',
'a9',
'aa',
'ab',
'ac',
'ad',
'ae',
'af',
'b0',
'b1',
'b2',
'b3',
'b4',
'b5',
'b6',
'b7',
'b8',
'b9',
'ba',
'bb',
'bc',
'bd',
'be',
'bf',
'c0',
'c1',
'c2',
'c3',
'c4',
'c5',
'c6',
'c7',
'c8',
'c9',
'ca',
'cb',
'cc',
'cd',
'ce',
'cf',
'd0',
'd1',
'd2',
'd3',
'd4',
'd5',
'd6',
'd7',
'd8',
'd9',
'da',
'db',
'dc',
'dd',
'de',
'df',
'e0',
'e1',
'e2',
'e3',
'e4',
'e5',
'e6',
'e7',
'e8',
'e9',
'ea',
'eb',
'ec',
'ed',
'ee',
'ef',
'f0',
'f1',
'f2',
'f3',
'f4',
'f5',
'f6',
'f7',
'f8',
'f9',
'fa',
'fb',
'fc',
'fd',
'fe',
'ff' ];
321 const DEG2RAD =
Math.PI / 180;
322 const RAD2DEG = 180 /
Math.PI;
325 function generateUUID() {
327 const d0 =
Math.random() * 0xffffffff | 0;
328 const d1 =
Math.random() * 0xffffffff | 0;
329 const d2 =
Math.random() * 0xffffffff | 0;
330 const d3 =
Math.random() * 0xffffffff | 0;
331 const uuid = _lut[ d0 & 0xff ] + _lut[ d0 >> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] +
'-' +
332 _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] +
'-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] +
'-' +
333 _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] +
'-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] +
334 _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ];
337 return uuid.toLowerCase();
341 function clamp( value,
min,
max ) {
349 function euclideanModulo(
n,
m ) {
351 return ( (
n %
m ) +
m ) %
m;
356 function mapLinear(
x, a1, a2, b1, b2 ) {
358 return b1 + (
x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
363 function inverseLerp(
x,
y, value ) {
367 return ( value -
x ) / (
y -
x );
378 function lerp(
x,
y,
t ) {
380 return ( 1 -
t ) *
x +
t *
y;
385 function damp(
x,
y, lambda,
dt ) {
387 return lerp(
x,
y, 1 -
Math.exp( - lambda *
dt ) );
392 function pingpong(
x, length = 1 ) {
394 return length -
Math.abs( euclideanModulo(
x, length * 2 ) - length );
399 function smoothstep(
x,
min,
max ) {
401 if (
x <=
min )
return 0;
402 if (
x >=
max )
return 1;
406 return x *
x * ( 3 - 2 *
x );
410 function smootherstep(
x,
min,
max ) {
412 if (
x <=
min )
return 0;
413 if (
x >=
max )
return 1;
417 return x *
x *
x * (
x * (
x * 6 - 15 ) + 10 );
422 function randInt( low, high ) {
424 return low +
Math.floor(
Math.random() * ( high - low + 1 ) );
429 function randFloat( low, high ) {
431 return low +
Math.random() * ( high - low );
436 function randFloatSpread( range ) {
438 return range * ( 0.5 -
Math.random() );
443 function seededRandom(
s ) {
449 let
t = _seed += 0x6D2B79F5;
451 t =
Math.imul(
t ^
t >>> 15,
t | 1 );
453 t ^=
t +
Math.imul(
t ^
t >>> 7,
t | 61 );
455 return ( (
t ^
t >>> 14 ) >>> 0 ) / 4294967296;
465 function radToDeg( radians ) {
467 return radians * RAD2DEG;
471 function isPowerOfTwo( value ) {
473 return ( value & ( value - 1 ) ) === 0 && value !== 0;
477 function ceilPowerOfTwo( value ) {
483 function floorPowerOfTwo( value ) {
489 function setQuaternionFromProperEuler(
q,
a,
b,
c, order ) {
497 const cos =
Math.cos;
498 const sin =
Math.sin;
500 const c2 = cos(
b / 2 );
501 const s2 = sin(
b / 2 );
503 const c13 = cos( (
a +
c ) / 2 );
504 const s13 = sin( (
a +
c ) / 2 );
506 const c1_3 = cos( (
a -
c ) / 2 );
507 const s1_3 = sin( (
a -
c ) / 2 );
509 const c3_1 = cos( (
c -
a ) / 2 );
510 const s3_1 = sin( (
c -
a ) / 2 );
515 q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 );
519 q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 );
523 q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 );
527 q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 );
531 q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 );
535 q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 );
539 console.warn(
'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order );
545 function denormalize( value, array ) {
547 switch ( array.constructor ) {
555 return value / 4294967295.0;
559 return value / 65535.0;
563 return value / 255.0;
567 return Math.max( value / 2147483647.0, - 1.0 );
571 return Math.max( value / 32767.0, - 1.0 );
575 return Math.max( value / 127.0, - 1.0 );
579 throw new Error(
'Invalid component type.' );
585 function normalize( value, array ) {
587 switch ( array.constructor ) {
595 return Math.round( value * 4294967295.0 );
599 return Math.round( value * 65535.0 );
603 return Math.round( value * 255.0 );
607 return Math.round( value * 2147483647.0 );
611 return Math.round( value * 32767.0 );
615 return Math.round( value * 127.0 );
619 throw new Error(
'Invalid component type.' );
628 generateUUID: generateUUID,
630 euclideanModulo: euclideanModulo,
631 mapLinear: mapLinear,
632 inverseLerp: inverseLerp,
636 smoothstep: smoothstep,
637 smootherstep: smootherstep,
639 randFloat: randFloat,
640 randFloatSpread: randFloatSpread,
641 seededRandom: seededRandom,
644 isPowerOfTwo: isPowerOfTwo,
645 ceilPowerOfTwo: ceilPowerOfTwo,
646 floorPowerOfTwo: floorPowerOfTwo,
647 setQuaternionFromProperEuler: setQuaternionFromProperEuler,
648 normalize: normalize,
649 denormalize: denormalize
654 constructor(
x = 0,
y = 0 ) {
656 Vector2.prototype.isVector2 =
true;
681 set height( value ) {
696 setScalar( scalar ) {
721 setComponent( index, value ) {
725 case 0: this.
x = value;
break;
726 case 1: this.
y = value;
break;
727 default:
throw new Error(
'index is out of range: ' + index );
735 getComponent( index ) {
739 case 0:
return this.
x;
740 case 1:
return this.
y;
741 default:
throw new Error(
'index is out of range: ' + index );
749 return new this.constructor( this.
x, this.
y );
789 addScaledVector(
v,
s ) {
834 multiplyScalar( scalar ) {
852 divideScalar( scalar ) {
854 return this.multiplyScalar( 1 / scalar );
860 const x = this.
x,
y = this.
y;
861 const e =
m.elements;
863 this.
x =
e[ 0 ] *
x +
e[ 3 ] *
y +
e[ 6 ];
864 this.
y =
e[ 1 ] *
x +
e[ 4 ] *
y +
e[ 7 ];
872 this.
x =
Math.min( this.
x,
v.x );
873 this.
y =
Math.min( this.
y,
v.y );
881 this.
x =
Math.max( this.
x,
v.x );
882 this.
y =
Math.max( this.
y,
v.y );
899 clampScalar( minVal, maxVal ) {
901 this.
x =
Math.max( minVal,
Math.min( maxVal,
this.x ) );
902 this.
y =
Math.max( minVal,
Math.min( maxVal,
this.y ) );
910 const length = this.length();
912 return this.divideScalar( length || 1 ).multiplyScalar(
Math.max(
min,
Math.min(
max, length ) ) );
918 this.
x =
Math.floor( this.
x );
919 this.
y =
Math.floor( this.
y );
927 this.
x =
Math.ceil( this.
x );
928 this.
y =
Math.ceil( this.
y );
936 this.
x =
Math.round( this.
x );
937 this.
y =
Math.round( this.
y );
945 this.
x =
Math.trunc( this.
x );
946 this.
y =
Math.trunc( this.
y );
963 return this.
x *
v.x + this.
y *
v.y;
969 return this.
x *
v.y - this.
y *
v.x;
975 return this.
x * this.
x + this.
y * this.
y;
981 return Math.sqrt( this.
x * this.
x + this.
y * this.
y );
987 return Math.abs( this.
x ) +
Math.abs( this.
y );
993 return this.divideScalar( this.length() || 1 );
1001 const angle =
Math.atan2( - this.
y, - this.
x ) +
Math.PI;
1009 const denominator =
Math.sqrt( this.lengthSq() *
v.lengthSq() );
1011 if ( denominator === 0 )
return Math.PI / 2;
1013 const theta = this.dot(
v ) / denominator;
1017 return Math.acos( clamp( theta, - 1, 1 ) );
1023 return Math.sqrt( this.distanceToSquared(
v ) );
1027 distanceToSquared(
v ) {
1029 const dx = this.
x -
v.x, dy = this.
y -
v.y;
1030 return dx * dx + dy * dy;
1034 manhattanDistanceTo(
v ) {
1036 return Math.abs( this.
x -
v.x ) +
Math.abs( this.
y -
v.y );
1042 return this.normalize().multiplyScalar( length );
1048 this.
x += (
v.x - this.
x ) * alpha;
1049 this.
y += (
v.y - this.
y ) * alpha;
1055 lerpVectors(
v1,
v2, alpha ) {
1057 this.
x =
v1.x + (
v2.x -
v1.x ) * alpha;
1058 this.
y =
v1.y + (
v2.y -
v1.y ) * alpha;
1066 return ( (
v.x ===
this.x ) && (
v.y ===
this.y ) );
1072 this.
x = array[ offset ];
1073 this.
y = array[ offset + 1 ];
1079 toArray( array = [], offset = 0 ) {
1081 array[ offset ] = this.
x;
1082 array[ offset + 1 ] = this.
y;
1088 fromBufferAttribute( attribute, index ) {
1090 this.
x = attribute.getX( index );
1091 this.
y = attribute.getY( index );
1097 rotateAround( center, angle ) {
1099 const c =
Math.cos( angle ),
s =
Math.sin( angle );
1101 const x = this.
x - center.x;
1102 const y = this.
y - center.y;
1104 this.
x =
x *
c -
y *
s + center.x;
1105 this.
y =
x *
s +
y *
c + center.y;
1113 this.
x =
Math.random();
1114 this.
y =
Math.random();
1120 *[ Symbol.iterator ]() {
1131 constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
1133 Matrix3.prototype.isMatrix3 =
true;
1145 this.
set( n11, n12, n13, n21, n22, n23, n31, n32, n33 );
1151 set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) {
1153 const te = this.elements;
1155 te[ 0 ] = n11;
te[ 1 ] = n21;
te[ 2 ] = n31;
1156 te[ 3 ] = n12;
te[ 4 ] = n22;
te[ 5 ] = n32;
1157 te[ 6 ] = n13;
te[ 7 ] = n23;
te[ 8 ] = n33;
1179 const te = this.elements;
1180 const me =
m.elements;
1182 te[ 0 ] =
me[ 0 ];
te[ 1 ] =
me[ 1 ];
te[ 2 ] =
me[ 2 ];
1183 te[ 3 ] =
me[ 3 ];
te[ 4 ] =
me[ 4 ];
te[ 5 ] =
me[ 5 ];
1184 te[ 6 ] =
me[ 6 ];
te[ 7 ] =
me[ 7 ];
te[ 8 ] =
me[ 8 ];
1190 extractBasis( xAxis, yAxis, zAxis ) {
1192 xAxis.setFromMatrix3Column(
this, 0 );
1193 yAxis.setFromMatrix3Column(
this, 1 );
1194 zAxis.setFromMatrix3Column(
this, 2 );
1200 setFromMatrix4(
m ) {
1202 const me =
m.elements;
1206 me[ 0 ],
me[ 4 ],
me[ 8 ],
1207 me[ 1 ],
me[ 5 ],
me[ 9 ],
1208 me[ 2 ],
me[ 6 ],
me[ 10 ]
1218 return this.multiplyMatrices(
this,
m );
1224 return this.multiplyMatrices(
m,
this );
1228 multiplyMatrices(
a,
b ) {
1230 const ae =
a.elements;
1231 const be =
b.elements;
1232 const te = this.elements;
1234 const a11 =
ae[ 0 ], a12 =
ae[ 3 ], a13 =
ae[ 6 ];
1235 const a21 =
ae[ 1 ], a22 =
ae[ 4 ], a23 =
ae[ 7 ];
1236 const a31 =
ae[ 2 ], a32 =
ae[ 5 ], a33 =
ae[ 8 ];
1238 const b11 =
be[ 0 ], b12 =
be[ 3 ], b13 =
be[ 6 ];
1239 const b21 =
be[ 1 ], b22 =
be[ 4 ], b23 =
be[ 7 ];
1240 const b31 =
be[ 2 ], b32 =
be[ 5 ], b33 =
be[ 8 ];
1242 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31;
1243 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32;
1244 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33;
1246 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31;
1247 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32;
1248 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33;
1250 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31;
1251 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32;
1252 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33;
1258 multiplyScalar(
s ) {
1260 const te = this.elements;
1262 te[ 0 ] *=
s;
te[ 3 ] *=
s;
te[ 6 ] *=
s;
1263 te[ 1 ] *=
s;
te[ 4 ] *=
s;
te[ 7 ] *=
s;
1264 te[ 2 ] *=
s;
te[ 5 ] *=
s;
te[ 8 ] *=
s;
1272 const te = this.elements;
1274 const a =
te[ 0 ],
b =
te[ 1 ],
c =
te[ 2 ],
1284 const te = this.elements,
1286 n11 =
te[ 0 ], n21 =
te[ 1 ], n31 =
te[ 2 ],
1287 n12 =
te[ 3 ], n22 =
te[ 4 ], n32 =
te[ 5 ],
1288 n13 =
te[ 6 ], n23 =
te[ 7 ], n33 =
te[ 8 ],
1290 t11 = n33 * n22 - n32 * n23,
1291 t12 = n32 * n13 - n33 * n12,
1292 t13 = n23 * n12 - n22 * n13,
1294 det = n11 * t11 + n21 * t12 + n31 * t13;
1296 if ( det === 0 )
return this.
set( 0, 0, 0, 0, 0, 0, 0, 0, 0 );
1298 const detInv = 1 / det;
1300 te[ 0 ] = t11 * detInv;
1301 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv;
1302 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv;
1304 te[ 3 ] = t12 * detInv;
1305 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv;
1306 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv;
1308 te[ 6 ] = t13 * detInv;
1309 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv;
1310 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv;
1319 const m = this.elements;
1321 tmp =
m[ 1 ];
m[ 1 ] =
m[ 3 ];
m[ 3 ] = tmp;
1322 tmp =
m[ 2 ];
m[ 2 ] =
m[ 6 ];
m[ 6 ] = tmp;
1323 tmp =
m[ 5 ];
m[ 5 ] =
m[ 7 ];
m[ 7 ] = tmp;
1329 getNormalMatrix( matrix4 ) {
1331 return this.setFromMatrix4( matrix4 ).invert().transpose();
1335 transposeIntoArray(
r ) {
1337 const m = this.elements;
1353 setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) {
1355 const c =
Math.cos( rotation );
1356 const s =
Math.sin( rotation );
1359 sx *
c, sx *
s, - sx * (
c * cx +
s * cy ) + cx + tx,
1360 - sy *
s, sy *
c, - sy * ( -
s * cx +
c * cy ) + cy + ty,
1372 this.premultiply( _m3.makeScale( sx, sy ) );
1380 this.premultiply( _m3.makeRotation( - theta ) );
1386 translate( tx, ty ) {
1388 this.premultiply( _m3.makeTranslation( tx, ty ) );
1396 makeTranslation(
x,
y ) {
1398 if (
x.isVector2 ) {
1424 makeRotation( theta ) {
1428 const c =
Math.cos( theta );
1429 const s =
Math.sin( theta );
1461 const te = this.elements;
1462 const me = matrix.elements;
1464 for ( let
i = 0;
i < 9;
i ++ ) {
1466 if (
te[
i ] !==
me[
i ] )
return false;
1476 for ( let
i = 0;
i < 9;
i ++ ) {
1478 this.elements[
i ] = array[
i + offset ];
1486 toArray( array = [], offset = 0 ) {
1488 const te = this.elements;
1490 array[ offset ] =
te[ 0 ];
1491 array[ offset + 1 ] =
te[ 1 ];
1492 array[ offset + 2 ] =
te[ 2 ];
1494 array[ offset + 3 ] =
te[ 3 ];
1495 array[ offset + 4 ] =
te[ 4 ];
1496 array[ offset + 5 ] =
te[ 5 ];
1498 array[ offset + 6 ] =
te[ 6 ];
1499 array[ offset + 7 ] =
te[ 7 ];
1500 array[ offset + 8 ] =
te[ 8 ];
1508 return new this.constructor().fromArray( this.elements );
1516 function arrayNeedsUint32( array ) {
1520 for ( let
i = array.length - 1;
i >= 0; --
i ) {
1522 if ( array[
i ] >= 65535 )
return true;
1530 const TYPED_ARRAYS = {
1542 function getTypedArray( type, buffer ) {
1544 return new TYPED_ARRAYS[ type ]( buffer );
1548 function createElementNS( name ) {
1550 return document.createElementNS(
'http://www.w3.org/1999/xhtml', name );
1554 function createCanvasElement() {
1556 const canvas = createElementNS(
'canvas' );
1557 canvas.style.display =
'block';
1564 function warnOnce( message ) {
1566 if ( message in _cache )
return;
1568 _cache[ message ] =
true;
1570 console.warn( message );
1586 const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 =
new Matrix3().set(
1587 0.8224621, 0.177538, 0.0,
1588 0.0331941, 0.9668058, 0.0,
1589 0.0170827, 0.0723974, 0.9105199,
1592 const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB =
new Matrix3().set(
1593 1.2249401, - 0.2249404, 0.0,
1594 - 0.0420569, 1.0420571, 0.0,
1595 - 0.0196376, - 0.0786361, 1.0982735
1602 const COLOR_SPACES = {
1603 [ LinearSRGBColorSpace ]: {
1604 transfer: LinearTransfer,
1605 primaries: Rec709Primaries,
1606 toReference: ( color ) => color,
1607 fromReference: ( color ) => color,
1609 [ SRGBColorSpace ]: {
1610 transfer: SRGBTransfer,
1611 primaries: Rec709Primaries,
1612 toReference: ( color ) => color.convertSRGBToLinear(),
1613 fromReference: ( color ) => color.convertLinearToSRGB(),
1615 [ LinearDisplayP3ColorSpace ]: {
1616 transfer: LinearTransfer,
1617 primaries: P3Primaries,
1618 toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ),
1619 fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ),
1621 [ DisplayP3ColorSpace ]: {
1622 transfer: SRGBTransfer,
1623 primaries: P3Primaries,
1624 toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ),
1625 fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(),
1629 const SUPPORTED_WORKING_COLOR_SPACES =
new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] );
1631 const ColorManagement = {
1635 _workingColorSpace: LinearSRGBColorSpace,
1637 get workingColorSpace() {
1639 return this._workingColorSpace;
1643 set workingColorSpace( colorSpace ) {
1645 if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) {
1647 throw new Error( `Unsupported working color space,
"${ colorSpace }".` );
1651 this._workingColorSpace = colorSpace;
1655 convert:
function ( color, sourceColorSpace, targetColorSpace ) {
1657 if ( this.enabled ===
false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) {
1663 const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference;
1664 const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference;
1666 return targetFromReference( sourceToReference( color ) );
1670 fromWorkingColorSpace:
function ( color, targetColorSpace ) {
1672 return this.convert( color, this._workingColorSpace, targetColorSpace );
1676 toWorkingColorSpace:
function ( color, sourceColorSpace ) {
1678 return this.convert( color, sourceColorSpace, this._workingColorSpace );
1682 getPrimaries:
function ( colorSpace ) {
1684 return COLOR_SPACES[ colorSpace ].primaries;
1688 getTransfer:
function ( colorSpace ) {
1690 if ( colorSpace === NoColorSpace )
return LinearTransfer;
1692 return COLOR_SPACES[ colorSpace ].transfer;
1699 function SRGBToLinear(
c ) {
1701 return (
c < 0.04045 ) ?
c * 0.0773993808 :
Math.pow(
c * 0.9478672986 + 0.0521327014, 2.4 );
1705 function LinearToSRGB(
c ) {
1707 return (
c < 0.0031308 ) ?
c * 12.92 : 1.055 * (
Math.pow(
c, 0.41666 ) ) - 0.055;
1715 static getDataURL( image ) {
1717 if ( /^data:/
i.test( image.src ) ) {
1723 if ( typeof HTMLCanvasElement ===
'undefined' ) {
1731 if ( image instanceof HTMLCanvasElement ) {
1737 if ( _canvas ===
undefined ) _canvas = createElementNS(
'canvas' );
1739 _canvas.width = image.width;
1740 _canvas.height = image.height;
1742 const context = _canvas.getContext(
'2d' );
1744 if ( image instanceof ImageData ) {
1746 context.putImageData( image, 0, 0 );
1750 context.drawImage( image, 0, 0, image.width, image.height );
1758 if ( canvas.width > 2048 || canvas.height > 2048 ) {
1760 console.warn(
'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image );
1762 return canvas.toDataURL(
'image/jpeg', 0.6 );
1766 return canvas.toDataURL(
'image/png' );
1772 static sRGBToLinear( image ) {
1774 if ( ( typeof HTMLImageElement !==
'undefined' && image instanceof HTMLImageElement ) ||
1775 ( typeof HTMLCanvasElement !==
'undefined' && image instanceof HTMLCanvasElement ) ||
1776 ( typeof ImageBitmap !==
'undefined' && image instanceof ImageBitmap ) ) {
1778 const canvas = createElementNS(
'canvas' );
1780 canvas.width = image.width;
1781 canvas.height = image.height;
1783 const context = canvas.getContext(
'2d' );
1784 context.drawImage( image, 0, 0, image.width, image.height );
1786 const imageData = context.getImageData( 0, 0, image.width, image.height );
1787 const data = imageData.data;
1789 for ( let
i = 0;
i < data.length;
i ++ ) {
1791 data[
i ] = SRGBToLinear( data[
i ] / 255 ) * 255;
1795 context.putImageData( imageData, 0, 0 );
1799 }
else if ( image.data ) {
1801 const data = image.data.slice( 0 );
1803 for ( let
i = 0;
i < data.length;
i ++ ) {
1807 data[
i ] =
Math.floor( SRGBToLinear( data[
i ] / 255 ) * 255 );
1813 data[
i ] = SRGBToLinear( data[
i ] );
1822 height: image.height
1827 console.warn(
'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' );
1840 constructor( data =
null ) {
1842 this.isSource =
true;
1844 Object.defineProperty(
this,
'id', { value: _sourceId ++ } );
1846 this.uuid = generateUUID();
1854 set needsUpdate( value ) {
1856 if ( value ===
true ) this.
version ++;
1862 const isRootObject = ( meta ===
undefined || typeof meta ===
'string' );
1864 if ( ! isRootObject && meta.images[
this.uuid ] !==
undefined ) {
1866 return meta.images[ this.uuid ];
1875 const data = this.data;
1877 if ( data !==
null ) {
1881 if (
Array.isArray( data ) ) {
1887 for ( let
i = 0,
l = data.length;
i <
l;
i ++ ) {
1889 if ( data[
i ].isDataTexture ) {
1891 url.push( serializeImage( data[
i ].image ) );
1895 url.push( serializeImage( data[
i ] ) );
1905 url = serializeImage( data );
1913 if ( ! isRootObject ) {
1915 meta.images[ this.uuid ] = output;
1925 function serializeImage( image ) {
1927 if ( ( typeof HTMLImageElement !==
'undefined' && image instanceof HTMLImageElement ) ||
1928 ( typeof HTMLCanvasElement !==
'undefined' && image instanceof HTMLCanvasElement ) ||
1929 ( typeof ImageBitmap !==
'undefined' && image instanceof ImageBitmap ) ) {
1942 data:
Array.from( image.data ),
1944 height: image.height,
1945 type: image.data.constructor.name
1950 console.warn(
'THREE.Texture: Unable to serialize Texture.' );
1967 this.isTexture =
true;
1969 Object.defineProperty(
this,
'id', { value: _textureId ++ } );
1971 this.uuid = generateUUID();
1975 this.source =
new Source( image );
1978 this.mapping = mapping;
1984 this.magFilter = magFilter;
1985 this.minFilter = minFilter;
1987 this.anisotropy = anisotropy;
1989 this.format = format;
1990 this.internalFormat =
null;
1993 this.offset =
new Vector2( 0, 0 );
1994 this.repeat =
new Vector2( 1, 1 );
1995 this.center =
new Vector2( 0, 0 );
1998 this.matrixAutoUpdate =
true;
2001 this.generateMipmaps =
true;
2002 this.premultiplyAlpha =
false;
2004 this.unpackAlignment = 4;
2006 if ( typeof colorSpace ===
'string' ) {
2008 this.colorSpace = colorSpace;
2012 warnOnce(
'THREE.Texture: Property .encoding has been replaced by .colorSpace.' );
2013 this.colorSpace = colorSpace === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
2021 this.onUpdate =
null;
2023 this.isRenderTargetTexture =
false;
2024 this.needsPMREMUpdate =
false;
2030 return this.source.data;
2034 set image( value =
null ) {
2036 this.source.data = value;
2042 this.matrix.setUvTransform( this.offset.x,
this.offset.y,
this.repeat.x,
this.repeat.y,
this.rotation,
this.center.x,
this.center.y );
2048 return new this.constructor().copy(
this );
2054 this.name = source.name;
2056 this.source = source.source;
2057 this.mipmaps = source.mipmaps.slice( 0 );
2059 this.mapping = source.mapping;
2060 this.channel = source.channel;
2062 this.wrapS = source.wrapS;
2063 this.wrapT = source.wrapT;
2065 this.magFilter = source.magFilter;
2066 this.minFilter = source.minFilter;
2068 this.anisotropy = source.anisotropy;
2070 this.format = source.format;
2071 this.internalFormat = source.internalFormat;
2072 this.type = source.type;
2074 this.offset.copy( source.offset );
2075 this.repeat.copy( source.repeat );
2076 this.center.copy( source.center );
2077 this.rotation = source.rotation;
2079 this.matrixAutoUpdate = source.matrixAutoUpdate;
2080 this.matrix.copy( source.matrix );
2082 this.generateMipmaps = source.generateMipmaps;
2083 this.premultiplyAlpha = source.premultiplyAlpha;
2084 this.flipY = source.flipY;
2085 this.unpackAlignment = source.unpackAlignment;
2086 this.colorSpace = source.colorSpace;
2088 this.userData = JSON.parse( JSON.stringify( source.userData ) );
2090 this.needsUpdate =
true;
2098 const isRootObject = ( meta ===
undefined || typeof meta ===
'string' );
2100 if ( ! isRootObject && meta.textures[
this.uuid ] !==
undefined ) {
2102 return meta.textures[ this.uuid ];
2111 generator:
'Texture.toJSON'
2117 image: this.source.toJSON( meta ).uuid,
2119 mapping: this.mapping,
2120 channel: this.channel,
2122 repeat: [ this.repeat.x, this.repeat.y ],
2123 offset: [ this.offset.x, this.offset.y ],
2124 center: [ this.center.x, this.center.y ],
2125 rotation: this.rotation,
2127 wrap: [ this.wrapS, this.wrapT ],
2129 format: this.format,
2130 internalFormat: this.internalFormat,
2132 colorSpace: this.colorSpace,
2134 minFilter: this.minFilter,
2135 magFilter: this.magFilter,
2136 anisotropy: this.anisotropy,
2140 generateMipmaps: this.generateMipmaps,
2141 premultiplyAlpha: this.premultiplyAlpha,
2142 unpackAlignment: this.unpackAlignment
2146 if ( Object.keys(
this.userData ).length > 0 ) output.userData = this.userData;
2148 if ( ! isRootObject ) {
2150 meta.textures[ this.uuid ] = output;
2160 this.dispatchEvent( { type:
'dispose' } );
2166 if ( this.mapping !==
UVMapping )
return uv;
2168 uv.applyMatrix3( this.matrix );
2170 if ( uv.x < 0 || uv.x > 1 ) {
2172 switch ( this.wrapS ) {
2176 uv.x = uv.x -
Math.floor( uv.x );
2181 uv.x = uv.x < 0 ? 0 : 1;
2186 if (
Math.abs(
Math.floor( uv.x ) % 2 ) === 1 ) {
2188 uv.x =
Math.ceil( uv.x ) - uv.x;
2192 uv.x = uv.x -
Math.floor( uv.x );
2202 if ( uv.y < 0 || uv.y > 1 ) {
2204 switch ( this.wrapT ) {
2208 uv.y = uv.y -
Math.floor( uv.y );
2213 uv.y = uv.y < 0 ? 0 : 1;
2218 if (
Math.abs(
Math.floor( uv.y ) % 2 ) === 1 ) {
2220 uv.y =
Math.ceil( uv.y ) - uv.y;
2224 uv.y = uv.y -
Math.floor( uv.y );
2244 set needsUpdate( value ) {
2246 if ( value ===
true ) {
2249 this.source.needsUpdate =
true;
2257 warnOnce(
'THREE.Texture: Property .encoding has been replaced by .colorSpace.' );
2258 return this.colorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
2262 set encoding( encoding ) {
2264 warnOnce(
'THREE.Texture: Property .encoding has been replaced by .colorSpace.' );
2265 this.colorSpace = encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
2273 Texture.DEFAULT_ANISOTROPY = 1;
2277 constructor(
x = 0,
y = 0,
z = 0,
w = 1 ) {
2279 Vector4.prototype.isVector4 =
true;
2294 set width( value ) {
2306 set height( value ) {
2323 setScalar( scalar ) {
2366 setComponent( index, value ) {
2370 case 0: this.
x = value;
break;
2371 case 1: this.
y = value;
break;
2372 case 2: this.
z = value;
break;
2373 case 3: this.
w = value;
break;
2374 default:
throw new Error(
'index is out of range: ' + index );
2382 getComponent( index ) {
2386 case 0:
return this.
x;
2387 case 1:
return this.
y;
2388 case 2:
return this.
z;
2389 case 3:
return this.
w;
2390 default:
throw new Error(
'index is out of range: ' + index );
2398 return new this.constructor( this.
x, this.
y, this.
z, this.
w );
2435 addVectors(
a,
b ) {
2446 addScaledVector(
v,
s ) {
2479 subVectors(
a,
b ) {
2501 multiplyScalar( scalar ) {
2514 const x = this.
x,
y = this.
y,
z = this.
z,
w = this.
w;
2515 const e =
m.elements;
2517 this.
x =
e[ 0 ] *
x +
e[ 4 ] *
y +
e[ 8 ] *
z +
e[ 12 ] *
w;
2518 this.
y =
e[ 1 ] *
x +
e[ 5 ] *
y +
e[ 9 ] *
z +
e[ 13 ] *
w;
2519 this.
z =
e[ 2 ] *
x +
e[ 6 ] *
y +
e[ 10 ] *
z +
e[ 14 ] *
w;
2520 this.
w =
e[ 3 ] *
x +
e[ 7 ] *
y +
e[ 11 ] *
z +
e[ 15 ] *
w;
2526 divideScalar( scalar ) {
2528 return this.multiplyScalar( 1 / scalar );
2532 setAxisAngleFromQuaternion(
q ) {
2538 this.
w = 2 *
Math.acos(
q.w );
2540 const s =
Math.sqrt( 1 -
q.w *
q.w );
2560 setAxisAngleFromRotationMatrix(
m ) {
2567 const epsilon = 0.01,
2572 m11 =
te[ 0 ], m12 =
te[ 4 ], m13 =
te[ 8 ],
2573 m21 =
te[ 1 ], m22 =
te[ 5 ], m23 =
te[ 9 ],
2574 m31 =
te[ 2 ], m32 =
te[ 6 ], m33 =
te[ 10 ];
2576 if ( (
Math.abs( m12 - m21 ) < epsilon ) &&
2577 (
Math.abs( m13 - m31 ) < epsilon ) &&
2578 (
Math.abs( m23 - m32 ) < epsilon ) ) {
2584 if ( (
Math.abs( m12 + m21 ) < epsilon2 ) &&
2585 (
Math.abs( m13 + m31 ) < epsilon2 ) &&
2586 (
Math.abs( m23 + m32 ) < epsilon2 ) &&
2587 (
Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
2591 this.
set( 1, 0, 0, 0 );
2601 const xx = ( m11 + 1 ) / 2;
2602 const yy = ( m22 + 1 ) / 2;
2603 const zz = ( m33 + 1 ) / 2;
2604 const xy = ( m12 + m21 ) / 4;
2605 const xz = ( m13 + m31 ) / 4;
2606 const yz = ( m23 + m32 ) / 4;
2608 if ( ( xx > yy ) && ( xx > zz ) ) {
2612 if ( xx < epsilon ) {
2620 x =
Math.sqrt( xx );
2626 }
else if ( yy > zz ) {
2630 if ( yy < epsilon ) {
2638 y =
Math.sqrt( yy );
2648 if ( zz < epsilon ) {
2656 z =
Math.sqrt( zz );
2664 this.
set(
x,
y,
z, angle );
2672 let
s =
Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) +
2673 ( m13 - m31 ) * ( m13 - m31 ) +
2674 ( m21 - m12 ) * ( m21 - m12 ) );
2676 if (
Math.abs(
s ) < 0.001 )
s = 1;
2681 this.
x = ( m32 - m23 ) /
s;
2682 this.
y = ( m13 - m31 ) /
s;
2683 this.
z = ( m21 - m12 ) /
s;
2684 this.
w =
Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
2692 this.
x =
Math.min( this.
x,
v.x );
2693 this.
y =
Math.min( this.
y,
v.y );
2694 this.
z =
Math.min( this.
z,
v.z );
2695 this.
w =
Math.min( this.
w,
v.w );
2703 this.
x =
Math.max( this.
x,
v.x );
2704 this.
y =
Math.max( this.
y,
v.y );
2705 this.
z =
Math.max( this.
z,
v.z );
2706 this.
w =
Math.max( this.
w,
v.w );
2725 clampScalar( minVal, maxVal ) {
2727 this.
x =
Math.max( minVal,
Math.min( maxVal,
this.x ) );
2728 this.
y =
Math.max( minVal,
Math.min( maxVal,
this.y ) );
2729 this.
z =
Math.max( minVal,
Math.min( maxVal,
this.z ) );
2730 this.
w =
Math.max( minVal,
Math.min( maxVal,
this.w ) );
2736 clampLength(
min,
max ) {
2738 const length = this.length();
2740 return this.divideScalar( length || 1 ).multiplyScalar(
Math.max(
min,
Math.min(
max, length ) ) );
2746 this.
x =
Math.floor( this.
x );
2747 this.
y =
Math.floor( this.
y );
2748 this.
z =
Math.floor( this.
z );
2749 this.
w =
Math.floor( this.
w );
2757 this.
x =
Math.ceil( this.
x );
2758 this.
y =
Math.ceil( this.
y );
2759 this.
z =
Math.ceil( this.
z );
2760 this.
w =
Math.ceil( this.
w );
2768 this.
x =
Math.round( this.
x );
2769 this.
y =
Math.round( this.
y );
2770 this.
z =
Math.round( this.
z );
2771 this.
w =
Math.round( this.
w );
2779 this.
x =
Math.trunc( this.
x );
2780 this.
y =
Math.trunc( this.
y );
2781 this.
z =
Math.trunc( this.
z );
2782 this.
w =
Math.trunc( this.
w );
2801 return this.
x *
v.x + this.
y *
v.y + this.
z *
v.z + this.
w *
v.w;
2807 return this.
x * this.
x + this.
y * this.
y + this.
z * this.
z + this.
w * this.
w;
2813 return Math.sqrt( this.
x * this.
x + this.
y * this.
y + this.
z * this.
z + this.
w * this.
w );
2825 return this.divideScalar( this.length() || 1 );
2831 return this.normalize().multiplyScalar( length );
2837 this.
x += (
v.x - this.
x ) * alpha;
2838 this.
y += (
v.y - this.
y ) * alpha;
2839 this.
z += (
v.z - this.
z ) * alpha;
2840 this.
w += (
v.w - this.
w ) * alpha;
2846 lerpVectors(
v1,
v2, alpha ) {
2848 this.
x =
v1.x + (
v2.x -
v1.x ) * alpha;
2849 this.
y =
v1.y + (
v2.y -
v1.y ) * alpha;
2850 this.
z =
v1.z + (
v2.z -
v1.z ) * alpha;
2851 this.
w =
v1.w + (
v2.w -
v1.w ) * alpha;
2859 return ( (
v.x ===
this.x ) && (
v.y ===
this.y ) && (
v.z ===
this.z ) && (
v.w ===
this.w ) );
2865 this.
x = array[ offset ];
2866 this.
y = array[ offset + 1 ];
2867 this.
z = array[ offset + 2 ];
2868 this.
w = array[ offset + 3 ];
2874 toArray( array = [], offset = 0 ) {
2876 array[ offset ] = this.
x;
2877 array[ offset + 1 ] = this.
y;
2878 array[ offset + 2 ] = this.
z;
2879 array[ offset + 3 ] = this.
w;
2885 fromBufferAttribute( attribute, index ) {
2887 this.
x = attribute.getX( index );
2888 this.
y = attribute.getY( index );
2889 this.
z = attribute.getZ( index );
2890 this.
w = attribute.getW( index );
2898 this.
x =
Math.random();
2899 this.
y =
Math.random();
2900 this.
z =
Math.random();
2901 this.
w =
Math.random();
2907 *[ Symbol.iterator ]() {
2925 constructor( width = 1, height = 1, options = {} ) {
2929 this.isRenderTarget =
true;
2932 this.height = height;
2935 this.scissor =
new Vector4( 0, 0, width, height );
2936 this.scissorTest =
false;
2938 this.viewport =
new Vector4( 0, 0, width, height );
2940 const image = { width: width, height: height, depth: 1 };
2945 warnOnce(
'THREE.WebGLRenderTarget: option.encoding has been replaced by option.colorSpace.' );
2946 options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
2950 options = Object.assign( {
2951 generateMipmaps:
false,
2952 internalFormat:
null,
2955 stencilBuffer:
false,
2960 this.texture =
new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
2961 this.texture.isRenderTargetTexture =
true;
2963 this.texture.flipY =
false;
2964 this.texture.generateMipmaps = options.generateMipmaps;
2965 this.texture.internalFormat = options.internalFormat;
2967 this.depthBuffer = options.depthBuffer;
2968 this.stencilBuffer = options.stencilBuffer;
2970 this.depthTexture = options.depthTexture;
2972 this.samples = options.samples;
2976 setSize( width, height, depth = 1 ) {
2978 if ( this.width !== width || this.height !== height || this.depth !== depth ) {
2981 this.height = height;
2984 this.texture.image.width = width;
2985 this.texture.image.height = height;
2986 this.texture.image.depth = depth;
2992 this.viewport.set( 0, 0, width, height );
2993 this.scissor.set( 0, 0, width, height );
2999 return new this.constructor().copy(
this );
3005 this.width = source.width;
3006 this.height = source.height;
3007 this.depth = source.depth;
3009 this.scissor.copy( source.scissor );
3010 this.scissorTest = source.scissorTest;
3012 this.viewport.copy( source.viewport );
3014 this.texture = source.texture.clone();
3015 this.texture.isRenderTargetTexture =
true;
3019 const image = Object.assign( {}, source.texture.image );
3020 this.texture.source =
new Source( image );
3022 this.depthBuffer = source.depthBuffer;
3023 this.stencilBuffer = source.stencilBuffer;
3025 if ( source.depthTexture !==
null ) this.depthTexture = source.depthTexture.clone();
3027 this.samples = source.samples;
3035 this.dispatchEvent( { type:
'dispose' } );
3043 constructor( width = 1, height = 1, options = {} ) {
3045 super( width, height, options );
3047 this.isWebGLRenderTarget =
true;
3053 class DataArrayTexture
extends Texture {
3055 constructor( data =
null, width = 1, height = 1, depth = 1 ) {
3059 this.isDataArrayTexture =
true;
3061 this.image = { data, width, height, depth };
3068 this.generateMipmaps =
false;
3070 this.unpackAlignment = 1;
3078 constructor( width = 1, height = 1, depth = 1, options = {} ) {
3080 super( width, height, options );
3082 this.isWebGLArrayRenderTarget =
true;
3086 this.texture =
new DataArrayTexture(
null, width, height, depth );
3088 this.texture.isRenderTargetTexture =
true;
3094 class Data3DTexture
extends Texture {
3096 constructor( data =
null, width = 1, height = 1, depth = 1 ) {
3108 this.isData3DTexture =
true;
3110 this.image = { data, width, height, depth };
3117 this.generateMipmaps =
false;
3119 this.unpackAlignment = 1;
3127 constructor( width = 1, height = 1, depth = 1, options = {} ) {
3129 super( width, height, options );
3131 this.isWebGL3DRenderTarget =
true;
3135 this.texture =
new Data3DTexture(
null, width, height, depth );
3137 this.texture.isRenderTargetTexture =
true;
3145 constructor( width = 1, height = 1, count = 1, options = {} ) {
3147 super( width, height, options );
3149 this.isWebGLMultipleRenderTargets =
true;
3151 const texture = this.texture;
3155 for ( let
i = 0;
i < count;
i ++ ) {
3157 this.texture[
i ] = texture.clone();
3158 this.texture[
i ].isRenderTargetTexture =
true;
3164 setSize( width, height, depth = 1 ) {
3166 if ( this.width !== width || this.height !== height || this.depth !== depth ) {
3169 this.height = height;
3172 for ( let
i = 0, il = this.texture.length;
i < il;
i ++ ) {
3174 this.texture[
i ].image.width = width;
3175 this.texture[
i ].image.height = height;
3176 this.texture[
i ].image.depth = depth;
3184 this.viewport.set( 0, 0, width, height );
3185 this.scissor.set( 0, 0, width, height );
3193 this.width = source.width;
3194 this.height = source.height;
3195 this.depth = source.depth;
3197 this.scissor.copy( source.scissor );
3198 this.scissorTest = source.scissorTest;
3200 this.viewport.copy( source.viewport );
3202 this.depthBuffer = source.depthBuffer;
3203 this.stencilBuffer = source.stencilBuffer;
3205 if ( source.depthTexture !==
null ) this.depthTexture = source.depthTexture.clone();
3207 this.texture.length = 0;
3209 for ( let
i = 0, il = source.texture.length;
i < il;
i ++ ) {
3211 this.texture[
i ] = source.texture[
i ].clone();
3212 this.texture[
i ].isRenderTargetTexture =
true;
3224 constructor(
x = 0,
y = 0,
z = 0,
w = 1 ) {
3226 this.isQuaternion =
true;
3235 static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1,
t ) {
3239 let x0 = src0[ srcOffset0 + 0 ],
3240 y0 = src0[ srcOffset0 + 1 ],
3241 z0 = src0[ srcOffset0 + 2 ],
3242 w0 = src0[ srcOffset0 + 3 ];
3244 const x1 = src1[ srcOffset1 + 0 ],
3245 y1 = src1[ srcOffset1 + 1 ],
3246 z1 = src1[ srcOffset1 + 2 ],
3247 w1 = src1[ srcOffset1 + 3 ];
3251 dst[ dstOffset + 0 ] = x0;
3252 dst[ dstOffset + 1 ] = y0;
3253 dst[ dstOffset + 2 ] = z0;
3254 dst[ dstOffset + 3 ] = w0;
3261 dst[ dstOffset + 0 ] = x1;
3262 dst[ dstOffset + 1 ] = y1;
3263 dst[ dstOffset + 2 ] = z1;
3264 dst[ dstOffset + 3 ] = w1;
3269 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) {
3272 const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1,
3273 dir = ( cos >= 0 ? 1 : - 1 ),
3274 sqrSin = 1 - cos * cos;
3277 if ( sqrSin >
Number.EPSILON ) {
3279 const sin =
Math.sqrt( sqrSin ),
3280 len =
Math.atan2( sin, cos * dir );
3282 s =
Math.sin(
s * len ) / sin;
3283 t =
Math.sin(
t * len ) / sin;
3287 const tDir =
t * dir;
3289 x0 = x0 *
s + x1 * tDir;
3290 y0 = y0 *
s + y1 * tDir;
3291 z0 = z0 *
s + z1 * tDir;
3292 w0 = w0 *
s + w1 * tDir;
3295 if (
s === 1 -
t ) {
3297 const f = 1 /
Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 );
3308 dst[ dstOffset ] = x0;
3309 dst[ dstOffset + 1 ] = y0;
3310 dst[ dstOffset + 2 ] = z0;
3311 dst[ dstOffset + 3 ] = w0;
3315 static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) {
3317 const x0 = src0[ srcOffset0 ];
3318 const y0 = src0[ srcOffset0 + 1 ];
3319 const z0 = src0[ srcOffset0 + 2 ];
3320 const w0 = src0[ srcOffset0 + 3 ];
3322 const x1 = src1[ srcOffset1 ];
3323 const y1 = src1[ srcOffset1 + 1 ];
3324 const z1 = src1[ srcOffset1 + 2 ];
3325 const w1 = src1[ srcOffset1 + 3 ];
3327 dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1;
3328 dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1;
3329 dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1;
3330 dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
3345 this._onChangeCallback();
3358 this._onChangeCallback();
3371 this._onChangeCallback();
3384 this._onChangeCallback();
3395 this._onChangeCallback();
3403 return new this.constructor( this._x, this._y, this._z, this._w );
3407 copy( quaternion ) {
3409 this._x = quaternion.x;
3410 this._y = quaternion.y;
3411 this._z = quaternion.z;
3412 this._w = quaternion.w;
3414 this._onChangeCallback();
3420 setFromEuler( euler,
update =
true ) {
3422 const x = euler._x,
y = euler._y,
z = euler._z, order = euler._order;
3428 const cos =
Math.cos;
3429 const sin =
Math.sin;
3431 const c1 = cos(
x / 2 );
3432 const c2 = cos(
y / 2 );
3433 const c3 = cos(
z / 2 );
3435 const s1 = sin(
x / 2 );
3436 const s2 = sin(
y / 2 );
3437 const s3 = sin(
z / 2 );
3442 this._x = s1 * c2 * c3 + c1 * s2 * s3;
3443 this._y = c1 * s2 * c3 - s1 * c2 * s3;
3444 this._z = c1 * c2 * s3 + s1 * s2 * c3;
3445 this._w = c1 * c2 * c3 - s1 * s2 * s3;
3449 this._x = s1 * c2 * c3 + c1 * s2 * s3;
3450 this._y = c1 * s2 * c3 - s1 * c2 * s3;
3451 this._z = c1 * c2 * s3 - s1 * s2 * c3;
3452 this._w = c1 * c2 * c3 + s1 * s2 * s3;
3456 this._x = s1 * c2 * c3 - c1 * s2 * s3;
3457 this._y = c1 * s2 * c3 + s1 * c2 * s3;
3458 this._z = c1 * c2 * s3 + s1 * s2 * c3;
3459 this._w = c1 * c2 * c3 - s1 * s2 * s3;
3463 this._x = s1 * c2 * c3 - c1 * s2 * s3;
3464 this._y = c1 * s2 * c3 + s1 * c2 * s3;
3465 this._z = c1 * c2 * s3 - s1 * s2 * c3;
3466 this._w = c1 * c2 * c3 + s1 * s2 * s3;
3470 this._x = s1 * c2 * c3 + c1 * s2 * s3;
3471 this._y = c1 * s2 * c3 + s1 * c2 * s3;
3472 this._z = c1 * c2 * s3 - s1 * s2 * c3;
3473 this._w = c1 * c2 * c3 - s1 * s2 * s3;
3477 this._x = s1 * c2 * c3 - c1 * s2 * s3;
3478 this._y = c1 * s2 * c3 - s1 * c2 * s3;
3479 this._z = c1 * c2 * s3 + s1 * s2 * c3;
3480 this._w = c1 * c2 * c3 + s1 * s2 * s3;
3484 console.warn(
'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order );
3488 if (
update ===
true ) this._onChangeCallback();
3494 setFromAxisAngle( axis, angle ) {
3500 const halfAngle = angle / 2,
s =
Math.sin( halfAngle );
3502 this._x = axis.x *
s;
3503 this._y = axis.y *
s;
3504 this._z = axis.z *
s;
3505 this._w =
Math.cos( halfAngle );
3507 this._onChangeCallback();
3513 setFromRotationMatrix(
m ) {
3519 const te =
m.elements,
3521 m11 =
te[ 0 ], m12 =
te[ 4 ], m13 =
te[ 8 ],
3522 m21 =
te[ 1 ], m22 =
te[ 5 ], m23 =
te[ 9 ],
3523 m31 =
te[ 2 ], m32 =
te[ 6 ], m33 =
te[ 10 ],
3525 trace = m11 + m22 + m33;
3529 const s = 0.5 /
Math.sqrt( trace + 1.0 );
3532 this._x = ( m32 - m23 ) *
s;
3533 this._y = ( m13 - m31 ) *
s;
3534 this._z = ( m21 - m12 ) *
s;
3536 }
else if ( m11 > m22 && m11 > m33 ) {
3538 const s = 2.0 *
Math.sqrt( 1.0 + m11 - m22 - m33 );
3540 this._w = ( m32 - m23 ) /
s;
3542 this._y = ( m12 + m21 ) /
s;
3543 this._z = ( m13 + m31 ) /
s;
3545 }
else if ( m22 > m33 ) {
3547 const s = 2.0 *
Math.sqrt( 1.0 + m22 - m11 - m33 );
3549 this._w = ( m13 - m31 ) /
s;
3550 this._x = ( m12 + m21 ) /
s;
3552 this._z = ( m23 + m32 ) /
s;
3556 const s = 2.0 *
Math.sqrt( 1.0 + m33 - m11 - m22 );
3558 this._w = ( m21 - m12 ) /
s;
3559 this._x = ( m13 + m31 ) /
s;
3560 this._y = ( m23 + m32 ) /
s;
3565 this._onChangeCallback();
3571 setFromUnitVectors( vFrom, vTo ) {
3575 let
r = vFrom.dot( vTo ) + 1;
3583 if (
Math.abs( vFrom.x ) >
Math.abs( vFrom.z ) ) {
3585 this._x = - vFrom.y;
3593 this._y = - vFrom.z;
3603 this._x = vFrom.y * vTo.z - vFrom.z * vTo.y;
3604 this._y = vFrom.z * vTo.x - vFrom.x * vTo.z;
3605 this._z = vFrom.x * vTo.y - vFrom.y * vTo.x;
3610 return this.normalize();
3616 return 2 *
Math.acos(
Math.abs( clamp( this.dot(
q ), - 1, 1 ) ) );
3620 rotateTowards(
q, step ) {
3622 const angle = this.angleTo(
q );
3624 if ( angle === 0 )
return this;
3626 const t =
Math.min( 1, step / angle );
3636 return this.
set( 0, 0, 0, 1 );
3644 return this.conjugate();
3654 this._onChangeCallback();
3662 return this._x *
v._x + this._y *
v._y + this._z *
v._z + this._w *
v._w;
3668 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
3674 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w );
3680 let
l = this.length();
3693 this._x = this._x *
l;
3694 this._y = this._y *
l;
3695 this._z = this._z *
l;
3696 this._w = this._w *
l;
3700 this._onChangeCallback();
3708 return this.multiplyQuaternions(
this,
q );
3714 return this.multiplyQuaternions(
q,
this );
3718 multiplyQuaternions(
a,
b ) {
3722 const qax =
a._x, qay =
a._y, qaz =
a._z, qaw =
a._w;
3723 const qbx =
b._x, qby =
b._y, qbz =
b._z, qbw =
b._w;
3725 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
3726 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
3727 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
3728 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
3730 this._onChangeCallback();
3738 if (
t === 0 )
return this;
3739 if (
t === 1 )
return this.
copy( qb );
3741 const x = this._x,
y = this._y,
z = this._z,
w = this._w;
3745 let cosHalfTheta =
w * qb._w +
x * qb._x +
y * qb._y +
z * qb._z;
3747 if ( cosHalfTheta < 0 ) {
3754 cosHalfTheta = - cosHalfTheta;
3762 if ( cosHalfTheta >= 1.0 ) {
3773 const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta;
3775 if ( sqrSinHalfTheta <=
Number.EPSILON ) {
3778 this._w =
s *
w +
t * this._w;
3779 this._x =
s *
x +
t * this._x;
3780 this._y =
s *
y +
t * this._y;
3781 this._z =
s *
z +
t * this._z;
3789 const sinHalfTheta =
Math.sqrt( sqrSinHalfTheta );
3790 const halfTheta =
Math.atan2( sinHalfTheta, cosHalfTheta );
3791 const ratioA =
Math.sin( ( 1 -
t ) * halfTheta ) / sinHalfTheta,
3792 ratioB =
Math.sin(
t * halfTheta ) / sinHalfTheta;
3794 this._w = (
w * ratioA + this._w * ratioB );
3795 this._x = (
x * ratioA + this._x * ratioB );
3796 this._y = (
y * ratioA + this._y * ratioB );
3797 this._z = (
z * ratioA + this._z * ratioB );
3799 this._onChangeCallback();
3805 slerpQuaternions( qa, qb,
t ) {
3807 return this.
copy( qa ).slerp( qb,
t );
3817 const u1 =
Math.random();
3818 const sqrt1u1 =
Math.sqrt( 1 - u1 );
3819 const sqrtu1 =
Math.sqrt( u1 );
3821 const u2 = 2 *
Math.PI *
Math.random();
3823 const u3 = 2 *
Math.PI *
Math.random();
3826 sqrt1u1 *
Math.cos( u2 ),
3827 sqrtu1 *
Math.sin( u3 ),
3828 sqrtu1 *
Math.cos( u3 ),
3829 sqrt1u1 *
Math.sin( u2 ),
3834 equals( quaternion ) {
3836 return ( quaternion._x ===
this._x ) && ( quaternion._y === this._y ) && ( quaternion._z ===
this._z ) && ( quaternion._w === this._w );
3842 this._x = array[ offset ];
3843 this._y = array[ offset + 1 ];
3844 this._z = array[ offset + 2 ];
3845 this._w = array[ offset + 3 ];
3847 this._onChangeCallback();
3853 toArray( array = [], offset = 0 ) {
3855 array[ offset ] = this._x;
3856 array[ offset + 1 ] = this._y;
3857 array[ offset + 2 ] = this._z;
3858 array[ offset + 3 ] = this._w;
3864 fromBufferAttribute( attribute, index ) {
3866 this._x = attribute.getX( index );
3867 this._y = attribute.getY( index );
3868 this._z = attribute.getZ( index );
3869 this._w = attribute.getW( index );
3871 this._onChangeCallback();
3879 return this.toArray();
3883 _onChange( callback ) {
3885 this._onChangeCallback = callback;
3891 _onChangeCallback() {}
3893 *[ Symbol.iterator ]() {
3906 constructor(
x = 0,
y = 0,
z = 0 ) {
3908 Vector3.prototype.isVector3 =
true;
3928 setScalar( scalar ) {
3962 setComponent( index, value ) {
3966 case 0: this.
x = value;
break;
3967 case 1: this.
y = value;
break;
3968 case 2: this.
z = value;
break;
3969 default:
throw new Error(
'index is out of range: ' + index );
3977 getComponent( index ) {
3981 case 0:
return this.
x;
3982 case 1:
return this.
y;
3983 case 2:
return this.
z;
3984 default:
throw new Error(
'index is out of range: ' + index );
3992 return new this.constructor( this.
x, this.
y, this.
z );
4026 addVectors(
a,
b ) {
4036 addScaledVector(
v,
s ) {
4066 subVectors(
a,
b ) {
4086 multiplyScalar( scalar ) {
4096 multiplyVectors(
a,
b ) {
4106 applyEuler( euler ) {
4108 return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) );
4112 applyAxisAngle( axis, angle ) {
4114 return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) );
4120 const x = this.
x,
y = this.
y,
z = this.
z;
4121 const e =
m.elements;
4123 this.
x =
e[ 0 ] *
x +
e[ 3 ] *
y +
e[ 6 ] *
z;
4124 this.
y =
e[ 1 ] *
x +
e[ 4 ] *
y +
e[ 7 ] *
z;
4125 this.
z =
e[ 2 ] *
x +
e[ 5 ] *
y +
e[ 8 ] *
z;
4131 applyNormalMatrix(
m ) {
4133 return this.applyMatrix3(
m ).normalize();
4139 const x = this.
x,
y = this.
y,
z = this.
z;
4140 const e =
m.elements;
4142 const w = 1 / (
e[ 3 ] *
x +
e[ 7 ] *
y +
e[ 11 ] *
z +
e[ 15 ] );
4144 this.
x = (
e[ 0 ] *
x +
e[ 4 ] *
y +
e[ 8 ] *
z +
e[ 12 ] ) *
w;
4145 this.
y = (
e[ 1 ] *
x +
e[ 5 ] *
y +
e[ 9 ] *
z +
e[ 13 ] ) *
w;
4146 this.
z = (
e[ 2 ] *
x +
e[ 6 ] *
y +
e[ 10 ] *
z +
e[ 14 ] ) *
w;
4152 applyQuaternion(
q ) {
4156 const vx = this.
x, vy = this.
y, vz = this.
z;
4157 const qx =
q.x, qy =
q.y, qz =
q.z, qw =
q.w;
4160 const tx = 2 * ( qy * vz - qz * vy );
4161 const ty = 2 * ( qz * vx - qx * vz );
4162 const tz = 2 * ( qx * vy - qy * vx );
4165 this.
x = vx + qw * tx + qy * tz - qz * ty;
4166 this.
y = vy + qw * ty + qz * tx - qx * tz;
4167 this.
z = vz + qw * tz + qx * ty - qy * tx;
4175 return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix );
4179 unproject( camera ) {
4181 return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld );
4185 transformDirection(
m ) {
4190 const x = this.
x,
y = this.
y,
z = this.
z;
4191 const e =
m.elements;
4193 this.
x =
e[ 0 ] *
x +
e[ 4 ] *
y +
e[ 8 ] *
z;
4194 this.
y =
e[ 1 ] *
x +
e[ 5 ] *
y +
e[ 9 ] *
z;
4195 this.
z =
e[ 2 ] *
x +
e[ 6 ] *
y +
e[ 10 ] *
z;
4197 return this.normalize();
4211 divideScalar( scalar ) {
4213 return this.multiplyScalar( 1 / scalar );
4219 this.
x =
Math.min( this.
x,
v.x );
4220 this.
y =
Math.min( this.
y,
v.y );
4221 this.
z =
Math.min( this.
z,
v.z );
4229 this.
x =
Math.max( this.
x,
v.x );
4230 this.
y =
Math.max( this.
y,
v.y );
4231 this.
z =
Math.max( this.
z,
v.z );
4249 clampScalar( minVal, maxVal ) {
4251 this.
x =
Math.max( minVal,
Math.min( maxVal,
this.x ) );
4252 this.
y =
Math.max( minVal,
Math.min( maxVal,
this.y ) );
4253 this.
z =
Math.max( minVal,
Math.min( maxVal,
this.z ) );
4259 clampLength(
min,
max ) {
4261 const length = this.length();
4263 return this.divideScalar( length || 1 ).multiplyScalar(
Math.max(
min,
Math.min(
max, length ) ) );
4269 this.
x =
Math.floor( this.
x );
4270 this.
y =
Math.floor( this.
y );
4271 this.
z =
Math.floor( this.
z );
4279 this.
x =
Math.ceil( this.
x );
4280 this.
y =
Math.ceil( this.
y );
4281 this.
z =
Math.ceil( this.
z );
4289 this.
x =
Math.round( this.
x );
4290 this.
y =
Math.round( this.
y );
4291 this.
z =
Math.round( this.
z );
4299 this.
x =
Math.trunc( this.
x );
4300 this.
y =
Math.trunc( this.
y );
4301 this.
z =
Math.trunc( this.
z );
4319 return this.
x *
v.x + this.
y *
v.y + this.
z *
v.z;
4327 return this.
x * this.
x + this.
y * this.
y + this.
z * this.
z;
4333 return Math.sqrt( this.
x * this.
x + this.
y * this.
y + this.
z * this.
z );
4345 return this.divideScalar( this.length() || 1 );
4351 return this.normalize().multiplyScalar( length );
4357 this.
x += (
v.x - this.
x ) * alpha;
4358 this.
y += (
v.y - this.
y ) * alpha;
4359 this.
z += (
v.z - this.
z ) * alpha;
4365 lerpVectors(
v1,
v2, alpha ) {
4367 this.
x =
v1.x + (
v2.x -
v1.x ) * alpha;
4368 this.
y =
v1.y + (
v2.y -
v1.y ) * alpha;
4369 this.
z =
v1.z + (
v2.z -
v1.z ) * alpha;
4377 return this.crossVectors(
this,
v );
4381 crossVectors(
a,
b ) {
4383 const ax =
a.x, ay =
a.y, az =
a.z;
4384 const bx =
b.x, by =
b.y, bz =
b.z;
4386 this.
x = ay * bz - az * by;
4387 this.
y = az * bx - ax * bz;
4388 this.
z = ax * by - ay * bx;
4394 projectOnVector(
v ) {
4396 const denominator =
v.lengthSq();
4398 if ( denominator === 0 )
return this.
set( 0, 0, 0 );
4400 const scalar =
v.dot(
this ) / denominator;
4402 return this.
copy(
v ).multiplyScalar( scalar );
4406 projectOnPlane( planeNormal ) {
4408 _vector$c.copy(
this ).projectOnVector( planeNormal );
4410 return this.sub( _vector$c );
4419 return this.sub( _vector$c.copy(
normal ).multiplyScalar( 2 *
this.dot(
normal ) ) );
4425 const denominator =
Math.sqrt( this.lengthSq() *
v.lengthSq() );
4427 if ( denominator === 0 )
return Math.PI / 2;
4429 const theta = this.dot(
v ) / denominator;
4433 return Math.acos( clamp( theta, - 1, 1 ) );
4439 return Math.sqrt( this.distanceToSquared(
v ) );
4443 distanceToSquared(
v ) {
4445 const dx = this.
x -
v.x, dy = this.
y -
v.y, dz = this.
z -
v.z;
4447 return dx * dx + dy * dy + dz * dz;
4451 manhattanDistanceTo(
v ) {
4453 return Math.abs( this.
x -
v.x ) +
Math.abs( this.
y -
v.y ) +
Math.abs( this.
z -
v.z );
4457 setFromSpherical(
s ) {
4459 return this.setFromSphericalCoords(
s.radius,
s.phi,
s.theta );
4463 setFromSphericalCoords( radius, phi, theta ) {
4465 const sinPhiRadius =
Math.sin( phi ) * radius;
4467 this.
x = sinPhiRadius *
Math.sin( theta );
4468 this.
y =
Math.cos( phi ) * radius;
4469 this.
z = sinPhiRadius *
Math.cos( theta );
4475 setFromCylindrical(
c ) {
4477 return this.setFromCylindricalCoords(
c.radius,
c.theta,
c.y );
4481 setFromCylindricalCoords( radius, theta,
y ) {
4483 this.
x = radius *
Math.sin( theta );
4485 this.
z = radius *
Math.cos( theta );
4491 setFromMatrixPosition(
m ) {
4493 const e =
m.elements;
4503 setFromMatrixScale(
m ) {
4505 const sx = this.setFromMatrixColumn(
m, 0 ).length();
4506 const sy = this.setFromMatrixColumn(
m, 1 ).length();
4507 const sz = this.setFromMatrixColumn(
m, 2 ).length();
4517 setFromMatrixColumn(
m, index ) {
4519 return this.
fromArray(
m.elements, index * 4 );
4523 setFromMatrix3Column(
m, index ) {
4525 return this.
fromArray(
m.elements, index * 3 );
4551 return ( (
v.x ===
this.x ) && (
v.y ===
this.y ) && (
v.z ===
this.z ) );
4557 this.
x = array[ offset ];
4558 this.
y = array[ offset + 1 ];
4559 this.
z = array[ offset + 2 ];
4565 toArray( array = [], offset = 0 ) {
4567 array[ offset ] = this.
x;
4568 array[ offset + 1 ] = this.
y;
4569 array[ offset + 2 ] = this.
z;
4575 fromBufferAttribute( attribute, index ) {
4577 this.
x = attribute.getX( index );
4578 this.
y = attribute.getY( index );
4579 this.
z = attribute.getZ( index );
4587 this.
x =
Math.random();
4588 this.
y =
Math.random();
4589 this.
z =
Math.random();
4599 const u = (
Math.random() - 0.5 ) * 2;
4601 const f =
Math.sqrt( 1 -
u ** 2 );
4611 *[ Symbol.iterator ]() {
4621 const _vector$c =
new Vector3();
4626 constructor(
min =
new Vector3( + Infinity, + Infinity, + Infinity ),
max =
new Vector3( - Infinity, - Infinity, - Infinity ) ) {
4644 setFromArray( array ) {
4648 for ( let
i = 0, il = array.length;
i < il;
i += 3 ) {
4650 this.expandByPoint( _vector$b.fromArray( array,
i ) );
4658 setFromBufferAttribute( attribute ) {
4662 for ( let
i = 0, il = attribute.count;
i < il;
i ++ ) {
4664 this.expandByPoint( _vector$b.fromBufferAttribute( attribute,
i ) );
4672 setFromPoints( points ) {
4676 for ( let
i = 0, il = points.length;
i < il;
i ++ ) {
4678 this.expandByPoint( points[
i ] );
4686 setFromCenterAndSize( center, size ) {
4688 const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 );
4690 this.
min.copy( center ).sub( halfSize );
4691 this.
max.copy( center ).add( halfSize );
4697 setFromObject(
object, precise =
false ) {
4701 return this.expandByObject(
object, precise );
4707 return new this.constructor().copy(
this );
4713 this.
min.copy( box.min );
4714 this.
max.copy( box.max );
4722 this.
min.x = this.
min.y = this.
min.z = + Infinity;
4723 this.
max.x = this.
max.y = this.
max.z = - Infinity;
4733 return ( this.
max.x <
this.min.x ) || ( this.
max.y < this.
min.y ) || ( this.
max.z <
this.min.z );
4737 getCenter( target ) {
4739 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.
min, this.
max ).multiplyScalar( 0.5 );
4745 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.
max, this.
min );
4749 expandByPoint( point ) {
4751 this.
min.min( point );
4752 this.
max.max( point );
4758 expandByVector( vector ) {
4760 this.
min.sub( vector );
4761 this.
max.add( vector );
4767 expandByScalar( scalar ) {
4769 this.
min.addScalar( - scalar );
4770 this.
max.addScalar( scalar );
4776 expandByObject(
object, precise =
false ) {
4781 object.updateWorldMatrix(
false,
false );
4783 const geometry =
object.geometry;
4787 const positionAttribute = geometry.getAttribute(
'position' );
4792 if ( precise ===
true && positionAttribute !==
undefined &&
object.isInstancedMesh !==
true ) {
4794 for ( let
i = 0,
l = positionAttribute.count;
i <
l;
i ++ ) {
4796 if (
object.isMesh ===
true ) {
4798 object.getVertexPosition(
i, _vector$b );
4802 _vector$b.fromBufferAttribute( positionAttribute,
i );
4806 _vector$b.applyMatrix4(
object.matrixWorld );
4807 this.expandByPoint( _vector$b );
4813 if (
object.boundingBox !==
undefined ) {
4817 if (
object.boundingBox ===
null ) {
4819 object.computeBoundingBox();
4823 _box$4.copy(
object.boundingBox );
4830 if ( geometry.boundingBox ===
null ) {
4832 geometry.computeBoundingBox();
4836 _box$4.copy( geometry.boundingBox );
4840 _box$4.applyMatrix4(
object.matrixWorld );
4842 this.
union( _box$4 );
4848 const children =
object.children;
4850 for ( let
i = 0,
l = children.length;
i <
l;
i ++ ) {
4852 this.expandByObject( children[
i ], precise );
4862 return point.x < this.
min.x || point.x > this.
max.x ||
4863 point.y < this.
min.y || point.y > this.
max.y ||
4864 point.z < this.
min.z || point.z > this.
max.z ? false :
true;
4868 containsBox( box ) {
4870 return this.
min.x <= box.min.x && box.max.x <= this.
max.x &&
4871 this.
min.y <= box.min.y && box.max.y <= this.
max.y &&
4872 this.
min.z <= box.min.z && box.max.z <= this.
max.z;
4876 getParameter( point, target ) {
4882 ( point.x -
this.min.x ) / (
this.max.x -
this.min.x ),
4883 ( point.y -
this.min.y ) / (
this.max.y -
this.min.y ),
4884 ( point.z -
this.min.z ) / (
this.max.z -
this.min.z )
4889 intersectsBox( box ) {
4892 return box.max.x < this.
min.x || box.min.x > this.
max.x ||
4893 box.max.y < this.
min.y || box.min.y > this.
max.y ||
4894 box.max.z < this.
min.z || box.min.z > this.
max.z ? false :
true;
4898 intersectsSphere( sphere ) {
4901 this.clampPoint( sphere.center, _vector$b );
4904 return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius );
4908 intersectsPlane( plane ) {
4915 if ( plane.normal.x > 0 ) {
4917 min = plane.normal.x * this.
min.x;
4918 max = plane.normal.x * this.
max.x;
4922 min = plane.normal.x * this.
max.x;
4923 max = plane.normal.x * this.
min.x;
4927 if ( plane.normal.y > 0 ) {
4929 min += plane.normal.y * this.
min.y;
4930 max += plane.normal.y * this.
max.y;
4934 min += plane.normal.y * this.
max.y;
4935 max += plane.normal.y * this.
min.y;
4939 if ( plane.normal.z > 0 ) {
4941 min += plane.normal.z * this.
min.z;
4942 max += plane.normal.z * this.
max.z;
4946 min += plane.normal.z * this.
max.z;
4947 max += plane.normal.z * this.
min.z;
4955 intersectsTriangle( triangle ) {
4957 if ( this.isEmpty() ) {
4964 this.getCenter( _center );
4965 _extents.subVectors( this.
max, _center );
4968 _v0$2.subVectors( triangle.a, _center );
4969 _v1$7.subVectors( triangle.b, _center );
4970 _v2$4.subVectors( triangle.c, _center );
4973 _f0.subVectors( _v1$7, _v0$2 );
4974 _f1.subVectors( _v2$4, _v1$7 );
4975 _f2.subVectors( _v0$2, _v2$4 );
4981 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y,
4982 _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x,
4983 - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0
4985 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
4992 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ];
4993 if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) {
5001 _triangleNormal.crossVectors( _f0, _f1 );
5002 axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ];
5004 return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents );
5008 clampPoint( point, target ) {
5010 return target.copy( point ).clamp( this.
min, this.
max );
5014 distanceToPoint( point ) {
5016 return this.clampPoint( point, _vector$b ).distanceTo( point );
5020 getBoundingSphere( target ) {
5022 if ( this.isEmpty() ) {
5028 this.getCenter( target.center );
5030 target.radius = this.getSize( _vector$b ).length() * 0.5;
5040 this.
min.max( box.min );
5041 this.
max.min( box.max );
5044 if ( this.isEmpty() ) this.makeEmpty();
5052 this.
min.min( box.min );
5053 this.
max.max( box.max );
5059 applyMatrix4( matrix ) {
5062 if ( this.isEmpty() )
return this;
5065 _points[ 0 ].set( this.
min.x,
this.min.y,
this.min.z ).applyMatrix4( matrix );
5066 _points[ 1 ].set( this.
min.x,
this.min.y,
this.max.z ).applyMatrix4( matrix );
5067 _points[ 2 ].set( this.
min.x,
this.max.y,
this.min.z ).applyMatrix4( matrix );
5068 _points[ 3 ].set( this.
min.x,
this.max.y,
this.max.z ).applyMatrix4( matrix );
5069 _points[ 4 ].set( this.
max.x,
this.min.y,
this.min.z ).applyMatrix4( matrix );
5070 _points[ 5 ].set( this.
max.x,
this.min.y,
this.max.z ).applyMatrix4( matrix );
5071 _points[ 6 ].set( this.
max.x,
this.max.y,
this.min.z ).applyMatrix4( matrix );
5072 _points[ 7 ].set( this.
max.x,
this.max.y,
this.max.z ).applyMatrix4( matrix );
5074 this.setFromPoints( _points );
5080 translate( offset ) {
5082 this.
min.add( offset );
5083 this.
max.add( offset );
5091 return box.min.equals( this.
min ) && box.max.equals( this.
max );
5108 const _vector$b =
new Vector3();
5110 const _box$4 =
new Box3();
5124 const _center =
new Vector3();
5125 const _extents =
new Vector3();
5126 const _triangleNormal =
new Vector3();
5127 const _testAxis =
new Vector3();
5129 function satForAxes( axes, v0,
v1,
v2, extents ) {
5131 for ( let
i = 0,
j = axes.length - 3;
i <=
j;
i += 3 ) {
5133 _testAxis.fromArray( axes,
i );
5135 const r = extents.x *
Math.abs( _testAxis.x ) + extents.y *
Math.abs( _testAxis.y ) + extents.z *
Math.abs( _testAxis.z );
5137 const p0 = v0.dot( _testAxis );
5138 const p1 =
v1.dot( _testAxis );
5139 const p2 =
v2.dot( _testAxis );
5141 if (
Math.max( -
Math.max( p0, p1, p2 ),
Math.min( p0, p1, p2 ) ) >
r ) {
5155 const _box$3 =
new Box3();
5161 constructor( center =
new Vector3(), radius = - 1 ) {
5163 this.isSphere =
true;
5165 this.center = center;
5166 this.radius = radius;
5170 set( center, radius ) {
5172 this.center.copy( center );
5173 this.radius = radius;
5179 setFromPoints( points, optionalCenter ) {
5181 const center = this.center;
5185 center.copy( optionalCenter );
5189 _box$3.setFromPoints( points ).getCenter( center );
5193 let maxRadiusSq = 0;
5195 for ( let
i = 0, il = points.length;
i < il;
i ++ ) {
5197 maxRadiusSq =
Math.max( maxRadiusSq, center.distanceToSquared( points[
i ] ) );
5201 this.radius =
Math.sqrt( maxRadiusSq );
5209 this.center.copy( sphere.center );
5210 this.radius = sphere.radius;
5218 return ( this.radius < 0 );
5224 this.center.set( 0, 0, 0 );
5233 return ( point.distanceToSquared(
this.center ) <= (
this.radius *
this.radius ) );
5237 distanceToPoint( point ) {
5239 return ( point.distanceTo(
this.center ) -
this.radius );
5243 intersectsSphere( sphere ) {
5245 const radiusSum = this.radius + sphere.radius;
5247 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum );
5251 intersectsBox( box ) {
5253 return box.intersectsSphere(
this );
5257 intersectsPlane( plane ) {
5259 return Math.abs( plane.distanceToPoint(
this.center ) ) <= this.radius;
5263 clampPoint( point, target ) {
5265 const deltaLengthSq = this.center.distanceToSquared( point );
5267 target.copy( point );
5269 if ( deltaLengthSq > ( this.radius * this.radius ) ) {
5271 target.sub( this.center ).normalize();
5272 target.multiplyScalar( this.radius ).add( this.center );
5282 if ( this.isEmpty() ) {
5290 target.set( this.center, this.center );
5291 target.expandByScalar( this.radius );
5297 applyMatrix4( matrix ) {
5299 this.center.applyMatrix4( matrix );
5300 this.radius = this.radius * matrix.getMaxScaleOnAxis();
5306 translate( offset ) {
5308 this.center.add( offset );
5314 expandByPoint( point ) {
5316 if ( this.isEmpty() ) {
5318 this.center.copy( point );
5326 _v1$6.subVectors( point, this.center );
5328 const lengthSq = _v1$6.lengthSq();
5330 if ( lengthSq > ( this.radius * this.radius ) ) {
5334 const length =
Math.sqrt( lengthSq );
5336 const delta = ( length - this.radius ) * 0.5;
5338 this.center.addScaledVector( _v1$6, delta / length );
5340 this.radius += delta;
5350 if ( sphere.isEmpty() ) {
5356 if ( this.isEmpty() ) {
5358 this.
copy( sphere );
5364 if ( this.center.equals( sphere.center ) ===
true ) {
5366 this.radius =
Math.max( this.radius, sphere.radius );
5370 _v2$3.subVectors( sphere.center,
this.center ).setLength( sphere.radius );
5372 this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) );
5374 this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) );
5384 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius );
5390 return new this.constructor().copy(
this );
5396 const _vector$a =
new Vector3();
5397 const _segCenter =
new Vector3();
5398 const _segDir =
new Vector3();
5403 const _normal$1 =
new Vector3();
5407 constructor( origin =
new Vector3(), direction =
new Vector3( 0, 0, - 1 ) ) {
5409 this.origin = origin;
5410 this.direction = direction;
5414 set( origin, direction ) {
5416 this.origin.copy( origin );
5417 this.direction.copy( direction );
5425 this.origin.copy( ray.origin );
5426 this.direction.copy( ray.direction );
5434 return target.copy( this.origin ).addScaledVector( this.direction,
t );
5440 this.direction.copy(
v ).sub( this.origin ).normalize();
5448 this.origin.copy( this.
at(
t, _vector$a ) );
5454 closestPointToPoint( point, target ) {
5456 target.subVectors( point, this.origin );
5458 const directionDistance = target.dot( this.direction );
5460 if ( directionDistance < 0 ) {
5462 return target.copy( this.origin );
5466 return target.copy( this.origin ).addScaledVector( this.direction, directionDistance );
5470 distanceToPoint( point ) {
5472 return Math.sqrt( this.distanceSqToPoint( point ) );
5476 distanceSqToPoint( point ) {
5478 const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction );
5482 if ( directionDistance < 0 ) {
5484 return this.origin.distanceToSquared( point );
5488 _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance );
5490 return _vector$a.distanceToSquared( point );
5494 distanceSqToSegment( v0,
v1, optionalPointOnRay, optionalPointOnSegment ) {
5503 _segCenter.copy( v0 ).add(
v1 ).multiplyScalar( 0.5 );
5504 _segDir.copy(
v1 ).sub( v0 ).normalize();
5505 _diff.copy( this.origin ).sub( _segCenter );
5507 const segExtent = v0.distanceTo(
v1 ) * 0.5;
5508 const a01 = - this.direction.dot( _segDir );
5509 const b0 = _diff.dot( this.direction );
5510 const b1 = - _diff.dot( _segDir );
5511 const c = _diff.lengthSq();
5512 const det =
Math.abs( 1 - a01 * a01 );
5513 let s0, s1, sqrDist, extDet;
5521 extDet = segExtent * det;
5525 if ( s1 >= - extDet ) {
5527 if ( s1 <= extDet ) {
5532 const invDet = 1 / det;
5535 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) +
c;
5542 s0 =
Math.max( 0, - ( a01 * s1 + b0 ) );
5543 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) +
c;
5552 s0 =
Math.max( 0, - ( a01 * s1 + b0 ) );
5553 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) +
c;
5559 if ( s1 <= - extDet ) {
5563 s0 =
Math.max( 0, - ( - a01 * segExtent + b0 ) );
5564 s1 = ( s0 > 0 ) ? - segExtent :
Math.
min(
Math.
max( - segExtent, - b1 ), segExtent );
5565 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) +
c;
5567 }
else if ( s1 <= extDet ) {
5572 s1 =
Math.min(
Math.max( - segExtent, - b1 ), segExtent );
5573 sqrDist = s1 * ( s1 + 2 * b1 ) +
c;
5579 s0 =
Math.max( 0, - ( a01 * segExtent + b0 ) );
5580 s1 = ( s0 > 0 ) ? segExtent :
Math.
min(
Math.
max( - segExtent, - b1 ), segExtent );
5581 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) +
c;
5591 s1 = ( a01 > 0 ) ? - segExtent : segExtent;
5592 s0 =
Math.max( 0, - ( a01 * s1 + b0 ) );
5593 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) +
c;
5597 if ( optionalPointOnRay ) {
5599 optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 );
5603 if ( optionalPointOnSegment ) {
5605 optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 );
5613 intersectSphere( sphere, target ) {
5615 _vector$a.subVectors( sphere.center,
this.origin );
5616 const tca = _vector$a.dot( this.direction );
5617 const d2 = _vector$a.dot( _vector$a ) - tca * tca;
5618 const radius2 = sphere.radius * sphere.radius;
5620 if ( d2 > radius2 )
return null;
5622 const thc =
Math.sqrt( radius2 - d2 );
5625 const t0 = tca - thc;
5628 const t1 = tca + thc;
5631 if ( t1 < 0 )
return null;
5636 if ( t0 < 0 )
return this.
at( t1, target );
5639 return this.
at( t0, target );
5643 intersectsSphere( sphere ) {
5645 return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius );
5649 distanceToPlane( plane ) {
5651 const denominator = plane.normal.dot( this.direction );
5653 if ( denominator === 0 ) {
5656 if ( plane.distanceToPoint(
this.origin ) === 0 ) {
5668 const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator;
5672 return t >= 0 ?
t :
null;
5676 intersectPlane( plane, target ) {
5678 const t = this.distanceToPlane( plane );
5686 return this.
at(
t, target );
5690 intersectsPlane( plane ) {
5694 const distToPoint = plane.distanceToPoint( this.origin );
5696 if ( distToPoint === 0 ) {
5702 const denominator = plane.normal.dot( this.direction );
5704 if ( denominator * distToPoint < 0 ) {
5716 intersectBox( box, target ) {
5718 let tmin, tmax, tymin, tymax, tzmin, tzmax;
5720 const invdirx = 1 / this.direction.x,
5721 invdiry = 1 / this.direction.y,
5722 invdirz = 1 / this.direction.z;
5724 const origin = this.origin;
5726 if ( invdirx >= 0 ) {
5728 tmin = ( box.min.x - origin.x ) * invdirx;
5729 tmax = ( box.max.x - origin.x ) * invdirx;
5733 tmin = ( box.max.x - origin.x ) * invdirx;
5734 tmax = ( box.min.x - origin.x ) * invdirx;
5738 if ( invdiry >= 0 ) {
5740 tymin = ( box.min.y - origin.y ) * invdiry;
5741 tymax = ( box.max.y - origin.y ) * invdiry;
5745 tymin = ( box.max.y - origin.y ) * invdiry;
5746 tymax = ( box.min.y - origin.y ) * invdiry;
5750 if ( ( tmin > tymax ) || ( tymin > tmax ) )
return null;
5752 if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin;
5754 if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax;
5756 if ( invdirz >= 0 ) {
5758 tzmin = ( box.min.z - origin.z ) * invdirz;
5759 tzmax = ( box.max.z - origin.z ) * invdirz;
5763 tzmin = ( box.max.z - origin.z ) * invdirz;
5764 tzmax = ( box.min.z - origin.z ) * invdirz;
5768 if ( ( tmin > tzmax ) || ( tzmin > tmax ) )
return null;
5770 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin;
5772 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax;
5776 if ( tmax < 0 )
return null;
5778 return this.
at( tmin >= 0 ? tmin : tmax, target );
5782 intersectsBox( box ) {
5784 return this.intersectBox( box, _vector$a ) !==
null;
5788 intersectTriangle(
a,
b,
c, backfaceCulling, target ) {
5794 _edge1.subVectors(
b,
a );
5795 _edge2.subVectors(
c,
a );
5796 _normal$1.crossVectors( _edge1, _edge2 );
5803 let DdN = this.direction.dot( _normal$1 );
5808 if ( backfaceCulling )
return null;
5811 }
else if ( DdN < 0 ) {
5822 _diff.subVectors( this.origin,
a );
5823 const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) );
5832 const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) );
5842 if ( DdQxE2 + DdE1xQ > DdN ) {
5849 const QdN = - sign * _diff.dot( _normal$1 );
5859 return this.
at( QdN / DdN, target );
5863 applyMatrix4( matrix4 ) {
5865 this.origin.applyMatrix4( matrix4 );
5866 this.direction.transformDirection( matrix4 );
5874 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction );
5880 return new this.constructor().copy(
this );
5888 constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5890 Matrix4.prototype.isMatrix4 =
true;
5903 this.
set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 );
5909 set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
5911 const te = this.elements;
5913 te[ 0 ] = n11;
te[ 4 ] = n12;
te[ 8 ] = n13;
te[ 12 ] = n14;
5914 te[ 1 ] = n21;
te[ 5 ] = n22;
te[ 9 ] = n23;
te[ 13 ] = n24;
5915 te[ 2 ] = n31;
te[ 6 ] = n32;
te[ 10 ] = n33;
te[ 14 ] = n34;
5916 te[ 3 ] = n41;
te[ 7 ] = n42;
te[ 11 ] = n43;
te[ 15 ] = n44;
5939 return new Matrix4().fromArray( this.elements );
5945 const te = this.elements;
5946 const me =
m.elements;
5948 te[ 0 ] =
me[ 0 ];
te[ 1 ] =
me[ 1 ];
te[ 2 ] =
me[ 2 ];
te[ 3 ] =
me[ 3 ];
5949 te[ 4 ] =
me[ 4 ];
te[ 5 ] =
me[ 5 ];
te[ 6 ] =
me[ 6 ];
te[ 7 ] =
me[ 7 ];
5950 te[ 8 ] =
me[ 8 ];
te[ 9 ] =
me[ 9 ];
te[ 10 ] =
me[ 10 ];
te[ 11 ] =
me[ 11 ];
5951 te[ 12 ] =
me[ 12 ];
te[ 13 ] =
me[ 13 ];
te[ 14 ] =
me[ 14 ];
te[ 15 ] =
me[ 15 ];
5959 const te = this.elements,
me =
m.elements;
5961 te[ 12 ] =
me[ 12 ];
5962 te[ 13 ] =
me[ 13 ];
5963 te[ 14 ] =
me[ 14 ];
5969 setFromMatrix3(
m ) {
5971 const me =
m.elements;
5975 me[ 0 ],
me[ 3 ],
me[ 6 ], 0,
5976 me[ 1 ],
me[ 4 ],
me[ 7 ], 0,
5977 me[ 2 ],
me[ 5 ],
me[ 8 ], 0,
5986 extractBasis( xAxis, yAxis, zAxis ) {
5988 xAxis.setFromMatrixColumn(
this, 0 );
5989 yAxis.setFromMatrixColumn(
this, 1 );
5990 zAxis.setFromMatrixColumn(
this, 2 );
5996 makeBasis( xAxis, yAxis, zAxis ) {
5999 xAxis.x, yAxis.x, zAxis.x, 0,
6000 xAxis.y, yAxis.y, zAxis.y, 0,
6001 xAxis.z, yAxis.z, zAxis.z, 0,
6009 extractRotation(
m ) {
6013 const te = this.elements;
6014 const me =
m.elements;
6016 const scaleX = 1 / _v1$5.setFromMatrixColumn(
m, 0 ).length();
6017 const scaleY = 1 / _v1$5.setFromMatrixColumn(
m, 1 ).length();
6018 const scaleZ = 1 / _v1$5.setFromMatrixColumn(
m, 2 ).length();
6020 te[ 0 ] =
me[ 0 ] * scaleX;
6021 te[ 1 ] =
me[ 1 ] * scaleX;
6022 te[ 2 ] =
me[ 2 ] * scaleX;
6025 te[ 4 ] =
me[ 4 ] * scaleY;
6026 te[ 5 ] =
me[ 5 ] * scaleY;
6027 te[ 6 ] =
me[ 6 ] * scaleY;
6030 te[ 8 ] =
me[ 8 ] * scaleZ;
6031 te[ 9 ] =
me[ 9 ] * scaleZ;
6032 te[ 10 ] =
me[ 10 ] * scaleZ;
6044 makeRotationFromEuler( euler ) {
6046 const te = this.elements;
6048 const x = euler.x,
y = euler.y,
z = euler.z;
6053 if ( euler.order ===
'XYZ' ) {
6061 te[ 1 ] = af +
be *
d;
6062 te[ 5 ] =
ae - bf *
d;
6065 te[ 2 ] = bf -
ae *
d;
6066 te[ 6 ] =
be + af *
d;
6069 }
else if ( euler.order ===
'YXZ' ) {
6073 te[ 0 ] =
ce + df *
b;
6074 te[ 4 ] =
de *
b - cf;
6081 te[ 2 ] = cf *
b -
de;
6082 te[ 6 ] = df +
ce *
b;
6085 }
else if ( euler.order ===
'ZXY' ) {
6089 te[ 0 ] =
ce - df *
b;
6091 te[ 8 ] =
de + cf *
b;
6093 te[ 1 ] = cf +
de *
b;
6095 te[ 9 ] = df -
ce *
b;
6101 }
else if ( euler.order ===
'ZYX' ) {
6106 te[ 4 ] =
be *
d - af;
6107 te[ 8 ] =
ae *
d + bf;
6110 te[ 5 ] = bf *
d +
ae;
6111 te[ 9 ] = af *
d -
be;
6117 }
else if ( euler.order ===
'YZX' ) {
6119 const ac =
a *
c, ad =
a *
d, bc =
b *
c, bd =
b *
d;
6122 te[ 4 ] = bd - ac *
f;
6123 te[ 8 ] = bc *
f + ad;
6130 te[ 6 ] = ad *
f + bc;
6131 te[ 10 ] = ac - bd *
f;
6133 }
else if ( euler.order ===
'XZY' ) {
6135 const ac =
a *
c, ad =
a *
d, bc =
b *
c, bd =
b *
d;
6141 te[ 1 ] = ac *
f + bd;
6143 te[ 9 ] = ad *
f - bc;
6145 te[ 2 ] = bc *
f - ad;
6147 te[ 10 ] = bd *
f + ac;
6166 makeRotationFromQuaternion(
q ) {
6168 return this.compose( _zero,
q, _one );
6172 lookAt( eye, target, up ) {
6174 const te = this.elements;
6176 _z.subVectors( eye, target );
6178 if ( _z.lengthSq() === 0 ) {
6187 _x.crossVectors( up, _z );
6189 if ( _x.lengthSq() === 0 ) {
6193 if (
Math.abs( up.z ) === 1 ) {
6204 _x.crossVectors( up, _z );
6209 _y.crossVectors( _z, _x );
6211 te[ 0 ] = _x.x;
te[ 4 ] = _y.x;
te[ 8 ] = _z.x;
6212 te[ 1 ] = _x.y;
te[ 5 ] = _y.y;
te[ 9 ] = _z.y;
6213 te[ 2 ] = _x.z;
te[ 6 ] = _y.z;
te[ 10 ] = _z.z;
6221 return this.multiplyMatrices(
this,
m );
6227 return this.multiplyMatrices(
m,
this );
6231 multiplyMatrices(
a,
b ) {
6233 const ae =
a.elements;
6234 const be =
b.elements;
6235 const te = this.elements;
6237 const a11 =
ae[ 0 ], a12 =
ae[ 4 ], a13 =
ae[ 8 ], a14 =
ae[ 12 ];
6238 const a21 =
ae[ 1 ], a22 =
ae[ 5 ], a23 =
ae[ 9 ], a24 =
ae[ 13 ];
6239 const a31 =
ae[ 2 ], a32 =
ae[ 6 ], a33 =
ae[ 10 ], a34 =
ae[ 14 ];
6240 const a41 =
ae[ 3 ], a42 =
ae[ 7 ], a43 =
ae[ 11 ], a44 =
ae[ 15 ];
6242 const b11 =
be[ 0 ], b12 =
be[ 4 ], b13 =
be[ 8 ], b14 =
be[ 12 ];
6243 const b21 =
be[ 1 ], b22 =
be[ 5 ], b23 =
be[ 9 ], b24 =
be[ 13 ];
6244 const b31 =
be[ 2 ], b32 =
be[ 6 ], b33 =
be[ 10 ], b34 =
be[ 14 ];
6245 const b41 =
be[ 3 ], b42 =
be[ 7 ], b43 =
be[ 11 ], b44 =
be[ 15 ];
6247 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
6248 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
6249 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
6250 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
6252 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
6253 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
6254 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
6255 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
6257 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
6258 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
6259 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
6260 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
6262 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
6263 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
6264 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
6265 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
6271 multiplyScalar(
s ) {
6273 const te = this.elements;
6275 te[ 0 ] *=
s;
te[ 4 ] *=
s;
te[ 8 ] *=
s;
te[ 12 ] *=
s;
6276 te[ 1 ] *=
s;
te[ 5 ] *=
s;
te[ 9 ] *=
s;
te[ 13 ] *=
s;
6277 te[ 2 ] *=
s;
te[ 6 ] *=
s;
te[ 10 ] *=
s;
te[ 14 ] *=
s;
6278 te[ 3 ] *=
s;
te[ 7 ] *=
s;
te[ 11 ] *=
s;
te[ 15 ] *=
s;
6286 const te = this.elements;
6288 const n11 =
te[ 0 ], n12 =
te[ 4 ], n13 =
te[ 8 ], n14 =
te[ 12 ];
6289 const n21 =
te[ 1 ], n22 =
te[ 5 ], n23 =
te[ 9 ], n24 =
te[ 13 ];
6290 const n31 =
te[ 2 ], n32 =
te[ 6 ], n33 =
te[ 10 ], n34 =
te[ 14 ];
6291 const n41 =
te[ 3 ], n42 =
te[ 7 ], n43 =
te[ 11 ], n44 =
te[ 15 ];
6336 const te = this.elements;
6339 tmp =
te[ 1 ];
te[ 1 ] =
te[ 4 ];
te[ 4 ] = tmp;
6340 tmp =
te[ 2 ];
te[ 2 ] =
te[ 8 ];
te[ 8 ] = tmp;
6341 tmp =
te[ 6 ];
te[ 6 ] =
te[ 9 ];
te[ 9 ] = tmp;
6343 tmp =
te[ 3 ];
te[ 3 ] =
te[ 12 ];
te[ 12 ] = tmp;
6344 tmp =
te[ 7 ];
te[ 7 ] =
te[ 13 ];
te[ 13 ] = tmp;
6345 tmp =
te[ 11 ];
te[ 11 ] =
te[ 14 ];
te[ 14 ] = tmp;
6351 setPosition(
x,
y,
z ) {
6353 const te = this.elements;
6355 if (
x.isVector3 ) {
6376 const te = this.elements,
6378 n11 =
te[ 0 ], n21 =
te[ 1 ], n31 =
te[ 2 ], n41 =
te[ 3 ],
6379 n12 =
te[ 4 ], n22 =
te[ 5 ], n32 =
te[ 6 ], n42 =
te[ 7 ],
6380 n13 =
te[ 8 ], n23 =
te[ 9 ], n33 =
te[ 10 ], n43 =
te[ 11 ],
6381 n14 =
te[ 12 ], n24 =
te[ 13 ], n34 =
te[ 14 ], n44 =
te[ 15 ],
6383 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44,
6384 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44,
6385 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44,
6386 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34;
6388 const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14;
6390 if ( det === 0 )
return this.
set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
6392 const detInv = 1 / det;
6394 te[ 0 ] = t11 * detInv;
6395 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv;
6396 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv;
6397 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv;
6399 te[ 4 ] = t12 * detInv;
6400 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv;
6401 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv;
6402 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv;
6404 te[ 8 ] = t13 * detInv;
6405 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv;
6406 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv;
6407 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv;
6409 te[ 12 ] = t14 * detInv;
6410 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv;
6411 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv;
6412 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv;
6420 const te = this.elements;
6421 const x =
v.x,
y =
v.y,
z =
v.z;
6423 te[ 0 ] *=
x;
te[ 4 ] *=
y;
te[ 8 ] *=
z;
6424 te[ 1 ] *=
x;
te[ 5 ] *=
y;
te[ 9 ] *=
z;
6425 te[ 2 ] *=
x;
te[ 6 ] *=
y;
te[ 10 ] *=
z;
6426 te[ 3 ] *=
x;
te[ 7 ] *=
y;
te[ 11 ] *=
z;
6432 getMaxScaleOnAxis() {
6434 const te = this.elements;
6436 const scaleXSq =
te[ 0 ] *
te[ 0 ] +
te[ 1 ] *
te[ 1 ] +
te[ 2 ] *
te[ 2 ];
6437 const scaleYSq =
te[ 4 ] *
te[ 4 ] +
te[ 5 ] *
te[ 5 ] +
te[ 6 ] *
te[ 6 ];
6438 const scaleZSq =
te[ 8 ] *
te[ 8 ] +
te[ 9 ] *
te[ 9 ] +
te[ 10 ] *
te[ 10 ];
6440 return Math.sqrt(
Math.max( scaleXSq, scaleYSq, scaleZSq ) );
6444 makeTranslation(
x,
y,
z ) {
6446 if (
x.isVector3 ) {
6474 makeRotationX( theta ) {
6476 const c =
Math.cos( theta ),
s =
Math.sin( theta );
6491 makeRotationY( theta ) {
6493 const c =
Math.cos( theta ),
s =
Math.sin( theta );
6508 makeRotationZ( theta ) {
6510 const c =
Math.cos( theta ),
s =
Math.sin( theta );
6525 makeRotationAxis( axis, angle ) {
6529 const c =
Math.cos( angle );
6530 const s =
Math.sin( angle );
6532 const x = axis.x,
y = axis.y,
z = axis.z;
6533 const tx =
t *
x, ty =
t *
y;
6537 tx *
x +
c, tx *
y -
s *
z, tx *
z +
s *
y, 0,
6538 tx *
y +
s *
z, ty *
y +
c, ty *
z -
s *
x, 0,
6539 tx *
z -
s *
y, ty *
z +
s *
x,
t *
z *
z +
c, 0,
6548 makeScale(
x,
y,
z ) {
6563 makeShear( xy, xz, yx, yz, zx, zy ) {
6578 compose(
position, quaternion, scale ) {
6580 const te = this.elements;
6582 const x = quaternion._x,
y = quaternion._y,
z = quaternion._z,
w = quaternion._w;
6583 const x2 =
x +
x, y2 =
y +
y, z2 =
z +
z;
6584 const xx =
x * x2, xy =
x * y2, xz =
x * z2;
6585 const yy =
y * y2, yz =
y * z2, zz =
z * z2;
6586 const wx =
w * x2, wy =
w * y2, wz =
w * z2;
6588 const sx = scale.x, sy = scale.y, sz = scale.z;
6590 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx;
6591 te[ 1 ] = ( xy + wz ) * sx;
6592 te[ 2 ] = ( xz - wy ) * sx;
6595 te[ 4 ] = ( xy - wz ) * sy;
6596 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy;
6597 te[ 6 ] = ( yz + wx ) * sy;
6600 te[ 8 ] = ( xz + wy ) * sz;
6601 te[ 9 ] = ( yz - wx ) * sz;
6602 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz;
6614 decompose(
position, quaternion, scale ) {
6616 const te = this.elements;
6618 let sx = _v1$5.set(
te[ 0 ],
te[ 1 ],
te[ 2 ] ).length();
6619 const sy = _v1$5.set(
te[ 4 ],
te[ 5 ],
te[ 6 ] ).length();
6620 const sz = _v1$5.set(
te[ 8 ],
te[ 9 ],
te[ 10 ] ).length();
6623 const det = this.determinant();
6624 if ( det < 0 ) sx = - sx;
6633 const invSX = 1 / sx;
6634 const invSY = 1 / sy;
6635 const invSZ = 1 / sz;
6637 _m1$2.elements[ 0 ] *= invSX;
6638 _m1$2.elements[ 1 ] *= invSX;
6639 _m1$2.elements[ 2 ] *= invSX;
6641 _m1$2.elements[ 4 ] *= invSY;
6642 _m1$2.elements[ 5 ] *= invSY;
6643 _m1$2.elements[ 6 ] *= invSY;
6645 _m1$2.elements[ 8 ] *= invSZ;
6646 _m1$2.elements[ 9 ] *= invSZ;
6647 _m1$2.elements[ 10 ] *= invSZ;
6649 quaternion.setFromRotationMatrix( _m1$2 );
6659 makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
6661 const te = this.elements;
6662 const x = 2 * near / ( right - left );
6663 const y = 2 * near / ( top - bottom );
6665 const a = ( right + left ) / ( right - left );
6666 const b = ( top + bottom ) / ( top - bottom );
6670 if ( coordinateSystem === WebGLCoordinateSystem ) {
6672 c = - ( far + near ) / ( far - near );
6673 d = ( - 2 * far * near ) / ( far - near );
6675 }
else if ( coordinateSystem === WebGPUCoordinateSystem ) {
6677 c = - far / ( far - near );
6678 d = ( - far * near ) / ( far - near );
6682 throw new Error(
'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem );
6686 te[ 0 ] =
x;
te[ 4 ] = 0;
te[ 8 ] =
a;
te[ 12 ] = 0;
6687 te[ 1 ] = 0;
te[ 5 ] =
y;
te[ 9 ] =
b;
te[ 13 ] = 0;
6688 te[ 2 ] = 0;
te[ 6 ] = 0;
te[ 10 ] =
c;
te[ 14 ] =
d;
6689 te[ 3 ] = 0;
te[ 7 ] = 0;
te[ 11 ] = - 1;
te[ 15 ] = 0;
6695 makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) {
6697 const te = this.elements;
6698 const w = 1.0 / ( right - left );
6699 const h = 1.0 / ( top - bottom );
6700 const p = 1.0 / ( far - near );
6702 const x = ( right + left ) *
w;
6703 const y = ( top + bottom ) *
h;
6707 if ( coordinateSystem === WebGLCoordinateSystem ) {
6709 z = ( far + near ) *
p;
6712 }
else if ( coordinateSystem === WebGPUCoordinateSystem ) {
6719 throw new Error(
'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem );
6723 te[ 0 ] = 2 *
w;
te[ 4 ] = 0;
te[ 8 ] = 0;
te[ 12 ] = -
x;
6724 te[ 1 ] = 0;
te[ 5 ] = 2 *
h;
te[ 9 ] = 0;
te[ 13 ] = -
y;
6725 te[ 2 ] = 0;
te[ 6 ] = 0;
te[ 10 ] = zInv;
te[ 14 ] = -
z;
6726 te[ 3 ] = 0;
te[ 7 ] = 0;
te[ 11 ] = 0;
te[ 15 ] = 1;
6734 const te = this.elements;
6735 const me = matrix.elements;
6737 for ( let
i = 0;
i < 16;
i ++ ) {
6739 if (
te[
i ] !==
me[
i ] )
return false;
6749 for ( let
i = 0;
i < 16;
i ++ ) {
6751 this.elements[
i ] = array[
i + offset ];
6759 toArray( array = [], offset = 0 ) {
6761 const te = this.elements;
6763 array[ offset ] =
te[ 0 ];
6764 array[ offset + 1 ] =
te[ 1 ];
6765 array[ offset + 2 ] =
te[ 2 ];
6766 array[ offset + 3 ] =
te[ 3 ];
6768 array[ offset + 4 ] =
te[ 4 ];
6769 array[ offset + 5 ] =
te[ 5 ];
6770 array[ offset + 6 ] =
te[ 6 ];
6771 array[ offset + 7 ] =
te[ 7 ];
6773 array[ offset + 8 ] =
te[ 8 ];
6774 array[ offset + 9 ] =
te[ 9 ];
6775 array[ offset + 10 ] =
te[ 10 ];
6776 array[ offset + 11 ] =
te[ 11 ];
6778 array[ offset + 12 ] =
te[ 12 ];
6779 array[ offset + 13 ] =
te[ 13 ];
6780 array[ offset + 14 ] =
te[ 14 ];
6781 array[ offset + 15 ] =
te[ 15 ];
6791 const _zero =
new Vector3( 0, 0, 0 );
6792 const _one =
new Vector3( 1, 1, 1 );
6797 const _matrix$1 =
new Matrix4();
6802 constructor(
x = 0,
y = 0,
z = 0, order =
Euler.DEFAULT_ORDER ) {
6804 this.isEuler =
true;
6809 this._order = order;
6822 this._onChangeCallback();
6835 this._onChangeCallback();
6848 this._onChangeCallback();
6858 set order( value ) {
6860 this._order = value;
6861 this._onChangeCallback();
6865 set(
x,
y,
z, order = this._order ) {
6870 this._order = order;
6872 this._onChangeCallback();
6880 return new this.constructor( this._x, this._y, this._z, this._order );
6889 this._order = euler._order;
6891 this._onChangeCallback();
6897 setFromRotationMatrix(
m, order = this._order,
update =
true ) {
6901 const te =
m.elements;
6902 const m11 =
te[ 0 ], m12 =
te[ 4 ], m13 =
te[ 8 ];
6903 const m21 =
te[ 1 ], m22 =
te[ 5 ], m23 =
te[ 9 ];
6904 const m31 =
te[ 2 ], m32 =
te[ 6 ], m33 =
te[ 10 ];
6910 this._y =
Math.asin( clamp( m13, - 1, 1 ) );
6912 if (
Math.abs( m13 ) < 0.9999999 ) {
6914 this._x =
Math.atan2( - m23, m33 );
6915 this._z =
Math.atan2( - m12, m11 );
6919 this._x =
Math.atan2( m32, m22 );
6928 this._x =
Math.asin( - clamp( m23, - 1, 1 ) );
6930 if (
Math.abs( m23 ) < 0.9999999 ) {
6932 this._y =
Math.atan2( m13, m33 );
6933 this._z =
Math.atan2( m21, m22 );
6937 this._y =
Math.atan2( - m31, m11 );
6946 this._x =
Math.asin( clamp( m32, - 1, 1 ) );
6948 if (
Math.abs( m32 ) < 0.9999999 ) {
6950 this._y =
Math.atan2( - m31, m33 );
6951 this._z =
Math.atan2( - m12, m22 );
6956 this._z =
Math.atan2( m21, m11 );
6964 this._y =
Math.asin( - clamp( m31, - 1, 1 ) );
6966 if (
Math.abs( m31 ) < 0.9999999 ) {
6968 this._x =
Math.atan2( m32, m33 );
6969 this._z =
Math.atan2( m21, m11 );
6974 this._z =
Math.atan2( - m12, m22 );
6982 this._z =
Math.asin( clamp( m21, - 1, 1 ) );
6984 if (
Math.abs( m21 ) < 0.9999999 ) {
6986 this._x =
Math.atan2( - m23, m22 );
6987 this._y =
Math.atan2( - m31, m11 );
6992 this._y =
Math.atan2( m13, m33 );
7000 this._z =
Math.asin( - clamp( m12, - 1, 1 ) );
7002 if (
Math.abs( m12 ) < 0.9999999 ) {
7004 this._x =
Math.atan2( m32, m22 );
7005 this._y =
Math.atan2( m13, m11 );
7009 this._x =
Math.atan2( - m23, m33 );
7018 console.warn(
'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order );
7022 this._order = order;
7024 if (
update ===
true ) this._onChangeCallback();
7030 setFromQuaternion(
q, order,
update ) {
7032 _matrix$1.makeRotationFromQuaternion(
q );
7034 return this.setFromRotationMatrix( _matrix$1, order,
update );
7038 setFromVector3(
v, order = this._order ) {
7040 return this.
set(
v.x,
v.y,
v.z, order );
7044 reorder( newOrder ) {
7048 _quaternion$3.setFromEuler(
this );
7050 return this.setFromQuaternion( _quaternion$3, newOrder );
7056 return ( euler._x ===
this._x ) && ( euler._y === this._y ) && ( euler._z ===
this._z ) && ( euler._order === this._order );
7062 this._x = array[ 0 ];
7063 this._y = array[ 1 ];
7064 this._z = array[ 2 ];
7065 if ( array[ 3 ] !==
undefined ) this._order = array[ 3 ];
7067 this._onChangeCallback();
7073 toArray( array = [], offset = 0 ) {
7075 array[ offset ] = this._x;
7076 array[ offset + 1 ] = this._y;
7077 array[ offset + 2 ] = this._z;
7078 array[ offset + 3 ] = this._order;
7084 _onChange( callback ) {
7086 this._onChangeCallback = callback;
7092 _onChangeCallback() {}
7094 *[ Symbol.iterator ]() {
7105 Euler.DEFAULT_ORDER =
'XYZ';
7117 this.mask = ( 1 << channel | 0 ) >>> 0;
7123 this.mask |= 1 << channel | 0;
7129 this.mask = 0xffffffff | 0;
7135 this.mask ^= 1 << channel | 0;
7139 disable( channel ) {
7141 this.mask &= ~ ( 1 << channel | 0 );
7153 return ( this.mask & layers.mask ) !== 0;
7157 isEnabled( channel ) {
7159 return ( this.mask & ( 1 << channel | 0 ) ) !== 0;
7165 let _object3DId = 0;
7170 const _target =
new Vector3();
7172 const _position$3 =
new Vector3();
7173 const _scale$2 =
new Vector3();
7176 const _xAxis =
new Vector3( 1, 0, 0 );
7177 const _yAxis =
new Vector3( 0, 1, 0 );
7178 const _zAxis =
new Vector3( 0, 0, 1 );
7180 const _addedEvent = { type:
'added' };
7181 const _removedEvent = { type:
'removed' };
7189 this.isObject3D =
true;
7191 Object.defineProperty(
this,
'id', { value: _object3DId ++ } );
7193 this.uuid = generateUUID();
7196 this.type =
'Object3D';
7201 this.up =
Object3D.DEFAULT_UP.clone();
7204 const rotation =
new Euler();
7206 const scale =
new Vector3( 1, 1, 1 );
7208 function onRotationChange() {
7210 quaternion.setFromEuler( rotation,
false );
7214 function onQuaternionChange() {
7216 rotation.setFromQuaternion( quaternion,
undefined,
false );
7220 rotation._onChange( onRotationChange );
7221 quaternion._onChange( onQuaternionChange );
7223 Object.defineProperties(
this, {
7253 this.matrixWorld =
new Matrix4();
7255 this.matrixAutoUpdate =
Object3D.DEFAULT_MATRIX_AUTO_UPDATE;
7257 this.matrixWorldAutoUpdate =
Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE;
7258 this.matrixWorldNeedsUpdate =
false;
7260 this.layers =
new Layers();
7261 this.visible =
true;
7263 this.castShadow =
false;
7264 this.receiveShadow =
false;
7266 this.frustumCulled =
true;
7267 this.renderOrder = 0;
7269 this.animations = [];
7275 onBeforeShadow( ) {}
7279 onBeforeRender( ) {}
7283 applyMatrix4( matrix ) {
7287 this.matrix.premultiply( matrix );
7289 this.matrix.decompose( this.
position, this.quaternion, this.scale );
7293 applyQuaternion(
q ) {
7295 this.quaternion.premultiply(
q );
7301 setRotationFromAxisAngle( axis, angle ) {
7305 this.quaternion.setFromAxisAngle( axis, angle );
7309 setRotationFromEuler( euler ) {
7311 this.quaternion.setFromEuler( euler,
true );
7315 setRotationFromMatrix(
m ) {
7319 this.quaternion.setFromRotationMatrix(
m );
7323 setRotationFromQuaternion(
q ) {
7327 this.quaternion.copy(
q );
7331 rotateOnAxis( axis, angle ) {
7336 _q1.setFromAxisAngle( axis, angle );
7338 this.quaternion.multiply( _q1 );
7344 rotateOnWorldAxis( axis, angle ) {
7350 _q1.setFromAxisAngle( axis, angle );
7352 this.quaternion.premultiply( _q1 );
7360 return this.rotateOnAxis( _xAxis, angle );
7366 return this.rotateOnAxis( _yAxis, angle );
7372 return this.rotateOnAxis( _zAxis, angle );
7376 translateOnAxis( axis, distance ) {
7381 _v1$4.copy( axis ).applyQuaternion( this.quaternion );
7383 this.
position.add( _v1$4.multiplyScalar( distance ) );
7389 translateX( distance ) {
7391 return this.translateOnAxis( _xAxis, distance );
7395 translateY( distance ) {
7397 return this.translateOnAxis( _yAxis, distance );
7401 translateZ( distance ) {
7403 return this.translateOnAxis( _zAxis, distance );
7407 localToWorld( vector ) {
7409 this.updateWorldMatrix(
true,
false );
7411 return vector.applyMatrix4( this.matrixWorld );
7415 worldToLocal( vector ) {
7417 this.updateWorldMatrix(
true,
false );
7419 return vector.applyMatrix4( _m1$1.copy(
this.matrixWorld ).invert() );
7427 if (
x.isVector3 ) {
7433 _target.set(
x,
y,
z );
7437 const parent = this.parent;
7439 this.updateWorldMatrix(
true,
false );
7441 _position$3.setFromMatrixPosition( this.matrixWorld );
7443 if ( this.isCamera || this.isLight ) {
7445 _m1$1.lookAt( _position$3, _target, this.up );
7449 _m1$1.lookAt( _target, _position$3, this.up );
7453 this.quaternion.setFromRotationMatrix( _m1$1 );
7457 _m1$1.extractRotation( parent.matrixWorld );
7458 _q1.setFromRotationMatrix( _m1$1 );
7459 this.quaternion.premultiply( _q1.invert() );
7467 if ( arguments.length > 1 ) {
7469 for ( let
i = 0;
i < arguments.length;
i ++ ) {
7471 this.
add( arguments[
i ] );
7479 if (
object ===
this ) {
7481 console.error(
'THREE.Object3D.add: object can\'t be added as a child of itself.',
object );
7486 if (
object &&
object.isObject3D ) {
7488 if (
object.parent !==
null ) {
7490 object.parent.remove(
object );
7494 object.parent =
this;
7495 this.children.push(
object );
7497 object.dispatchEvent( _addedEvent );
7501 console.error(
'THREE.Object3D.add: object not an instance of THREE.Object3D.',
object );
7511 if ( arguments.length > 1 ) {
7513 for ( let
i = 0;
i < arguments.length;
i ++ ) {
7515 this.
remove( arguments[
i ] );
7523 const index = this.children.indexOf(
object );
7525 if ( index !== - 1 ) {
7527 object.parent =
null;
7528 this.children.splice( index, 1 );
7530 object.dispatchEvent( _removedEvent );
7538 removeFromParent() {
7540 const parent = this.parent;
7542 if ( parent !==
null ) {
7544 parent.remove(
this );
7554 return this.
remove( ... this.children );
7564 this.updateWorldMatrix(
true,
false );
7566 _m1$1.copy( this.matrixWorld ).invert();
7568 if (
object.parent !==
null ) {
7570 object.parent.updateWorldMatrix(
true,
false );
7572 _m1$1.multiply(
object.parent.matrixWorld );
7576 object.applyMatrix4( _m1$1 );
7580 object.updateWorldMatrix(
false,
true );
7586 getObjectById(
id ) {
7588 return this.getObjectByProperty(
'id',
id );
7592 getObjectByName( name ) {
7594 return this.getObjectByProperty(
'name', name );
7598 getObjectByProperty( name, value ) {
7600 if (
this[ name ] === value )
return this;
7602 for ( let
i = 0,
l = this.children.length;
i <
l;
i ++ ) {
7604 const child = this.children[
i ];
7605 const object = child.getObjectByProperty( name, value );
7619 getObjectsByProperty( name, value, result = [] ) {
7621 if (
this[ name ] === value ) result.push(
this );
7623 const children = this.children;
7625 for ( let
i = 0,
l = children.length;
i <
l;
i ++ ) {
7627 children[
i ].getObjectsByProperty( name, value, result );
7635 getWorldPosition( target ) {
7637 this.updateWorldMatrix(
true,
false );
7639 return target.setFromMatrixPosition( this.matrixWorld );
7643 getWorldQuaternion( target ) {
7645 this.updateWorldMatrix(
true,
false );
7647 this.matrixWorld.decompose( _position$3, target, _scale$2 );
7653 getWorldScale( target ) {
7655 this.updateWorldMatrix(
true,
false );
7657 this.matrixWorld.decompose( _position$3, _quaternion$2, target );
7663 getWorldDirection( target ) {
7665 this.updateWorldMatrix(
true,
false );
7667 const e = this.matrixWorld.elements;
7669 return target.set(
e[ 8 ],
e[ 9 ],
e[ 10 ] ).normalize();
7675 traverse( callback ) {
7679 const children = this.children;
7681 for ( let
i = 0,
l = children.length;
i <
l;
i ++ ) {
7683 children[
i ].traverse( callback );
7689 traverseVisible( callback ) {
7691 if ( this.visible ===
false )
return;
7695 const children = this.children;
7697 for ( let
i = 0,
l = children.length;
i <
l;
i ++ ) {
7699 children[
i ].traverseVisible( callback );
7705 traverseAncestors( callback ) {
7707 const parent = this.parent;
7709 if ( parent !==
null ) {
7713 parent.traverseAncestors( callback );
7721 this.matrix.compose( this.
position, this.quaternion, this.scale );
7723 this.matrixWorldNeedsUpdate =
true;
7731 if ( this.matrixWorldNeedsUpdate || force ) {
7733 if ( this.parent ===
null ) {
7735 this.matrixWorld.copy( this.matrix );
7739 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld,
this.matrix );
7743 this.matrixWorldNeedsUpdate =
false;
7751 const children = this.children;
7753 for ( let
i = 0,
l = children.length;
i <
l;
i ++ ) {
7755 const child = children[
i ];
7757 if ( child.matrixWorldAutoUpdate ===
true || force ===
true ) {
7759 child.updateMatrixWorld( force );
7767 updateWorldMatrix( updateParents, updateChildren ) {
7769 const parent = this.parent;
7771 if ( updateParents ===
true && parent !==
null && parent.matrixWorldAutoUpdate ===
true ) {
7773 parent.updateWorldMatrix(
true,
false );
7779 if ( this.parent ===
null ) {
7781 this.matrixWorld.copy( this.matrix );
7785 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld,
this.matrix );
7791 if ( updateChildren ===
true ) {
7793 const children = this.children;
7795 for ( let
i = 0,
l = children.length;
i <
l;
i ++ ) {
7797 const child = children[
i ];
7799 if ( child.matrixWorldAutoUpdate ===
true ) {
7801 child.updateWorldMatrix(
false,
true );
7814 const isRootObject = ( meta ===
undefined || typeof meta ===
'string' );
7821 if ( isRootObject ) {
7838 generator:
'Object3D.toJSON'
7847 object.uuid = this.uuid;
7848 object.type = this.type;
7850 if ( this.name !==
'' )
object.name = this.name;
7851 if ( this.castShadow ===
true )
object.castShadow =
true;
7852 if ( this.receiveShadow ===
true )
object.receiveShadow =
true;
7853 if ( this.visible ===
false )
object.visible =
false;
7854 if ( this.frustumCulled ===
false )
object.frustumCulled =
false;
7855 if ( this.renderOrder !== 0 )
object.renderOrder = this.renderOrder;
7856 if ( Object.keys(
this.userData ).length > 0 )
object.userData = this.userData;
7858 object.layers = this.layers.mask;
7859 object.matrix = this.matrix.toArray();
7860 object.up = this.up.toArray();
7862 if ( this.matrixAutoUpdate ===
false )
object.matrixAutoUpdate =
false;
7866 if ( this.isInstancedMesh ) {
7868 object.type =
'InstancedMesh';
7869 object.count = this.count;
7870 object.instanceMatrix = this.instanceMatrix.toJSON();
7871 if ( this.instanceColor !==
null )
object.instanceColor = this.instanceColor.toJSON();
7875 if ( this.isBatchedMesh ) {
7877 object.type =
'BatchedMesh';
7878 object.perObjectFrustumCulled = this.perObjectFrustumCulled;
7879 object.sortObjects = this.sortObjects;
7881 object.drawRanges = this._drawRanges;
7882 object.reservedRanges = this._reservedRanges;
7884 object.visibility = this._visibility;
7885 object.active = this._active;
7886 object.bounds = this._bounds.map( bound => ( {
7887 boxInitialized: bound.boxInitialized,
7888 boxMin: bound.box.min.toArray(),
7889 boxMax: bound.box.max.toArray(),
7891 sphereInitialized: bound.sphereInitialized,
7892 sphereRadius: bound.sphere.radius,
7893 sphereCenter: bound.sphere.center.toArray()
7896 object.maxGeometryCount = this._maxGeometryCount;
7897 object.maxVertexCount = this._maxVertexCount;
7898 object.maxIndexCount = this._maxIndexCount;
7900 object.geometryInitialized = this._geometryInitialized;
7901 object.geometryCount = this._geometryCount;
7903 object.matricesTexture = this._matricesTexture.toJSON( meta );
7905 if ( this.boundingSphere !==
null ) {
7907 object.boundingSphere = {
7908 center:
object.boundingSphere.center.toArray(),
7909 radius:
object.boundingSphere.radius
7914 if ( this.boundingBox !==
null ) {
7916 object.boundingBox = {
7917 min:
object.boundingBox.min.toArray(),
7918 max:
object.boundingBox.max.toArray()
7927 function serialize( library, element ) {
7929 if ( library[ element.uuid ] ===
undefined ) {
7931 library[ element.uuid ] = element.toJSON( meta );
7935 return element.uuid;
7939 if ( this.isScene ) {
7941 if ( this.background ) {
7943 if ( this.background.isColor ) {
7945 object.background = this.background.toJSON();
7947 }
else if ( this.background.isTexture ) {
7949 object.background = this.background.toJSON( meta ).uuid;
7955 if ( this.environment && this.environment.isTexture &&
this.environment.isRenderTargetTexture !==
true ) {
7957 object.environment = this.environment.toJSON( meta ).uuid;
7961 }
else if ( this.isMesh || this.isLine || this.isPoints ) {
7963 object.geometry = serialize( meta.geometries,
this.geometry );
7965 const parameters = this.geometry.parameters;
7969 const shapes = parameters.shapes;
7971 if (
Array.isArray( shapes ) ) {
7973 for ( let
i = 0,
l = shapes.length;
i <
l;
i ++ ) {
7975 const shape = shapes[
i ];
7977 serialize( meta.shapes, shape );
7983 serialize( meta.shapes, shapes );
7991 if ( this.isSkinnedMesh ) {
7993 object.bindMode = this.bindMode;
7994 object.bindMatrix = this.bindMatrix.toArray();
7998 serialize( meta.skeletons,
this.skeleton );
8000 object.skeleton = this.skeleton.uuid;
8008 if (
Array.isArray(
this.material ) ) {
8012 for ( let
i = 0,
l = this.material.length;
i <
l;
i ++ ) {
8014 uuids.push( serialize( meta.materials,
this.material[
i ] ) );
8018 object.material = uuids;
8022 object.material = serialize( meta.materials,
this.material );
8030 if ( this.children.length > 0 ) {
8032 object.children = [];
8034 for ( let
i = 0;
i < this.children.length;
i ++ ) {
8036 object.children.push( this.children[
i ].toJSON( meta ).
object );
8044 if ( this.animations.length > 0 ) {
8046 object.animations = [];
8048 for ( let
i = 0;
i < this.animations.length;
i ++ ) {
8050 const animation = this.animations[
i ];
8052 object.animations.push( serialize( meta.animations, animation ) );
8058 if ( isRootObject ) {
8060 const geometries = extractFromCache( meta.geometries );
8061 const materials = extractFromCache( meta.materials );
8062 const textures = extractFromCache( meta.textures );
8063 const images = extractFromCache( meta.images );
8064 const shapes = extractFromCache( meta.shapes );
8065 const skeletons = extractFromCache( meta.skeletons );
8066 const animations = extractFromCache( meta.animations );
8067 const nodes = extractFromCache( meta.nodes );
8069 if ( geometries.length > 0 ) output.geometries = geometries;
8070 if ( materials.length > 0 ) output.materials = materials;
8071 if ( textures.length > 0 ) output.textures = textures;
8072 if ( images.length > 0 ) output.images = images;
8073 if ( shapes.length > 0 ) output.shapes = shapes;
8074 if ( skeletons.length > 0 ) output.skeletons = skeletons;
8075 if ( animations.length > 0 ) output.animations = animations;
8076 if ( nodes.length > 0 ) output.nodes = nodes;
8087 function extractFromCache(
cache ) {
8090 for (
const key in
cache ) {
8092 const data =
cache[ key ];
8093 delete data.metadata;
8094 values.push( data );
8104 clone( recursive ) {
8106 return new this.constructor().copy(
this, recursive );
8110 copy( source, recursive =
true ) {
8112 this.name = source.name;
8114 this.up.copy( source.up );
8116 this.
position.copy( source.position );
8117 this.rotation.order = source.rotation.order;
8118 this.quaternion.copy( source.quaternion );
8119 this.scale.copy( source.scale );
8121 this.matrix.copy( source.matrix );
8122 this.matrixWorld.copy( source.matrixWorld );
8124 this.matrixAutoUpdate = source.matrixAutoUpdate;
8126 this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate;
8127 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
8129 this.layers.mask = source.layers.mask;
8130 this.visible = source.visible;
8132 this.castShadow = source.castShadow;
8133 this.receiveShadow = source.receiveShadow;
8135 this.frustumCulled = source.frustumCulled;
8136 this.renderOrder = source.renderOrder;
8138 this.animations = source.animations.slice();
8140 this.userData = JSON.parse( JSON.stringify( source.userData ) );
8142 if ( recursive ===
true ) {
8144 for ( let
i = 0;
i < source.children.length;
i ++ ) {
8146 const child = source.children[
i ];
8147 this.
add( child.clone() );
8160 Object3D.DEFAULT_MATRIX_AUTO_UPDATE =
true;
8161 Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE =
true;
8175 let warnedGetUV =
false;
8187 static getNormal(
a,
b,
c, target ) {
8189 target.subVectors(
c,
b );
8190 _v0$1.subVectors(
a,
b );
8191 target.cross( _v0$1 );
8193 const targetLengthSq = target.lengthSq();
8194 if ( targetLengthSq > 0 ) {
8196 return target.multiplyScalar( 1 /
Math.sqrt( targetLengthSq ) );
8200 return target.set( 0, 0, 0 );
8206 static getBarycoord( point,
a,
b,
c, target ) {
8208 _v0$1.subVectors(
c,
a );
8209 _v1$3.subVectors(
b,
a );
8210 _v2$2.subVectors( point,
a );
8212 const dot00 = _v0$1.dot( _v0$1 );
8213 const dot01 = _v0$1.dot( _v1$3 );
8214 const dot02 = _v0$1.dot( _v2$2 );
8215 const dot11 = _v1$3.dot( _v1$3 );
8216 const dot12 = _v1$3.dot( _v2$2 );
8218 const denom = ( dot00 * dot11 - dot01 * dot01 );
8221 if ( denom === 0 ) {
8223 target.set( 0, 0, 0 );
8228 const invDenom = 1 / denom;
8229 const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
8230 const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
8233 return target.set( 1 -
u -
v,
v,
u );
8240 if ( this.getBarycoord( point,
a,
b,
c, _v3$1 ) ===
null ) {
8246 return ( _v3$1.x >= 0 ) && ( _v3$1.y >= 0 ) && ( ( _v3$1.x + _v3$1.y ) <= 1 );
8250 static getUV( point, p1, p2, p3, uv1, uv2, uv3, target ) {
8252 if ( warnedGetUV ===
false ) {
8254 console.warn(
'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' );
8260 return this.getInterpolation( point, p1, p2, p3, uv1, uv2, uv3, target );
8264 static getInterpolation( point, p1, p2, p3,
v1,
v2,
v3, target ) {
8266 if ( this.getBarycoord( point, p1, p2, p3, _v3$1 ) ===
null ) {
8270 if (
'z' in target ) target.z = 0;
8271 if (
'w' in target ) target.w = 0;
8276 target.setScalar( 0 );
8277 target.addScaledVector(
v1, _v3$1.x );
8278 target.addScaledVector(
v2, _v3$1.y );
8279 target.addScaledVector(
v3, _v3$1.z );
8285 static isFrontFacing(
a,
b,
c, direction ) {
8287 _v0$1.subVectors(
c,
b );
8288 _v1$3.subVectors(
a,
b );
8291 return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true :
false;
8305 setFromPointsAndIndices( points, i0, i1, i2 ) {
8307 this.
a.copy( points[ i0 ] );
8308 this.
b.copy( points[ i1 ] );
8309 this.
c.copy( points[ i2 ] );
8315 setFromAttributeAndIndices( attribute, i0, i1, i2 ) {
8317 this.
a.fromBufferAttribute( attribute, i0 );
8318 this.
b.fromBufferAttribute( attribute, i1 );
8319 this.
c.fromBufferAttribute( attribute, i2 );
8327 return new this.constructor().copy(
this );
8333 this.
a.copy( triangle.a );
8334 this.
b.copy( triangle.b );
8335 this.
c.copy( triangle.c );
8343 _v0$1.subVectors( this.
c, this.
b );
8344 _v1$3.subVectors( this.
a, this.
b );
8346 return _v0$1.cross( _v1$3 ).length() * 0.5;
8350 getMidpoint( target ) {
8352 return target.addVectors( this.
a, this.
b ).add( this.
c ).multiplyScalar( 1 / 3 );
8356 getNormal( target ) {
8358 return Triangle.getNormal( this.
a, this.
b, this.
c, target );
8362 getPlane( target ) {
8364 return target.setFromCoplanarPoints( this.
a, this.
b, this.
c );
8368 getBarycoord( point, target ) {
8370 return Triangle.getBarycoord( point, this.
a, this.
b, this.
c, target );
8374 getUV( point, uv1, uv2, uv3, target ) {
8376 if ( warnedGetUV ===
false ) {
8378 console.warn(
'THREE.Triangle.getUV() has been renamed to THREE.Triangle.getInterpolation().' );
8384 return Triangle.getInterpolation( point, this.
a, this.
b, this.
c, uv1, uv2, uv3, target );
8388 getInterpolation( point,
v1,
v2,
v3, target ) {
8390 return Triangle.getInterpolation( point, this.
a, this.
b, this.
c,
v1,
v2,
v3, target );
8396 return Triangle.containsPoint( point, this.
a, this.
b, this.
c );
8400 isFrontFacing( direction ) {
8402 return Triangle.isFrontFacing( this.
a, this.
b, this.
c, direction );
8406 intersectsBox( box ) {
8408 return box.intersectsTriangle(
this );
8412 closestPointToPoint(
p, target ) {
8414 const a = this.
a,
b = this.
b,
c = this.
c;
8423 _vab.subVectors(
b,
a );
8424 _vac.subVectors(
c,
a );
8425 _vap.subVectors(
p,
a );
8426 const d1 = _vab.dot( _vap );
8427 const d2 = _vac.dot( _vap );
8428 if ( d1 <= 0 && d2 <= 0 ) {
8431 return target.copy(
a );
8435 _vbp.subVectors(
p,
b );
8436 const d3 = _vab.dot( _vbp );
8437 const d4 = _vac.dot( _vbp );
8438 if ( d3 >= 0 && d4 <= d3 ) {
8441 return target.copy(
b );
8445 const vc = d1 * d4 - d3 * d2;
8446 if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) {
8448 v = d1 / ( d1 - d3 );
8450 return target.copy(
a ).addScaledVector( _vab,
v );
8454 _vcp.subVectors(
p,
c );
8455 const d5 = _vab.dot( _vcp );
8456 const d6 = _vac.dot( _vcp );
8457 if ( d6 >= 0 && d5 <= d6 ) {
8460 return target.copy(
c );
8464 const vb = d5 * d2 - d1 * d6;
8465 if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) {
8467 w = d2 / ( d2 - d6 );
8469 return target.copy(
a ).addScaledVector( _vac,
w );
8473 const va = d3 * d6 - d5 * d4;
8474 if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) {
8476 _vbc.subVectors(
c,
b );
8477 w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) );
8479 return target.copy(
b ).addScaledVector( _vbc,
w );
8484 const denom = 1 / ( va + vb + vc );
8489 return target.copy(
a ).addScaledVector( _vab,
v ).addScaledVector( _vac,
w );
8493 equals( triangle ) {
8495 return triangle.a.equals( this.
a ) && triangle.b.equals( this.
b ) && triangle.c.equals( this.
c );
8501 const _colorKeywords = {
'aliceblue': 0xF0F8FF,
'antiquewhite': 0xFAEBD7,
'aqua': 0x00FFFF,
'aquamarine': 0x7FFFD4,
'azure': 0xF0FFFF,
8502 'beige': 0xF5F5DC,
'bisque': 0xFFE4C4,
'black': 0x000000,
'blanchedalmond': 0xFFEBCD,
'blue': 0x0000FF,
'blueviolet': 0x8A2BE2,
8503 'brown': 0xA52A2A,
'burlywood': 0xDEB887,
'cadetblue': 0x5F9EA0,
'chartreuse': 0x7FFF00,
'chocolate': 0xD2691E,
'coral': 0xFF7F50,
8504 'cornflowerblue': 0x6495ED,
'cornsilk': 0xFFF8DC,
'crimson': 0xDC143C,
'cyan': 0x00FFFF,
'darkblue': 0x00008B,
'darkcyan': 0x008B8B,
8505 'darkgoldenrod': 0xB8860B,
'darkgray': 0xA9A9A9,
'darkgreen': 0x006400,
'darkgrey': 0xA9A9A9,
'darkkhaki': 0xBDB76B,
'darkmagenta': 0x8B008B,
8506 'darkolivegreen': 0x556B2F,
'darkorange': 0xFF8C00,
'darkorchid': 0x9932CC,
'darkred': 0x8B0000,
'darksalmon': 0xE9967A,
'darkseagreen': 0x8FBC8F,
8507 'darkslateblue': 0x483D8B,
'darkslategray': 0x2F4F4F,
'darkslategrey': 0x2F4F4F,
'darkturquoise': 0x00CED1,
'darkviolet': 0x9400D3,
8508 'deeppink': 0xFF1493,
'deepskyblue': 0x00BFFF,
'dimgray': 0x696969,
'dimgrey': 0x696969,
'dodgerblue': 0x1E90FF,
'firebrick': 0xB22222,
8509 'floralwhite': 0xFFFAF0,
'forestgreen': 0x228B22,
'fuchsia': 0xFF00FF,
'gainsboro': 0xDCDCDC,
'ghostwhite': 0xF8F8FF,
'gold': 0xFFD700,
8510 'goldenrod': 0xDAA520,
'gray': 0x808080,
'green': 0x008000,
'greenyellow': 0xADFF2F,
'grey': 0x808080,
'honeydew': 0xF0FFF0,
'hotpink': 0xFF69B4,
8511 'indianred': 0xCD5C5C,
'indigo': 0x4B0082,
'ivory': 0xFFFFF0,
'khaki': 0xF0E68C,
'lavender': 0xE6E6FA,
'lavenderblush': 0xFFF0F5,
'lawngreen': 0x7CFC00,
8512 'lemonchiffon': 0xFFFACD,
'lightblue': 0xADD8E6,
'lightcoral': 0xF08080,
'lightcyan': 0xE0FFFF,
'lightgoldenrodyellow': 0xFAFAD2,
'lightgray': 0xD3D3D3,
8513 'lightgreen': 0x90EE90,
'lightgrey': 0xD3D3D3,
'lightpink': 0xFFB6C1,
'lightsalmon': 0xFFA07A,
'lightseagreen': 0x20B2AA,
'lightskyblue': 0x87CEFA,
8514 'lightslategray': 0x778899,
'lightslategrey': 0x778899,
'lightsteelblue': 0xB0C4DE,
'lightyellow': 0xFFFFE0,
'lime': 0x00FF00,
'limegreen': 0x32CD32,
8515 'linen': 0xFAF0E6,
'magenta': 0xFF00FF,
'maroon': 0x800000,
'mediumaquamarine': 0x66CDAA,
'mediumblue': 0x0000CD,
'mediumorchid': 0xBA55D3,
8516 'mediumpurple': 0x9370DB,
'mediumseagreen': 0x3CB371,
'mediumslateblue': 0x7B68EE,
'mediumspringgreen': 0x00FA9A,
'mediumturquoise': 0x48D1CC,
8517 'mediumvioletred': 0xC71585,
'midnightblue': 0x191970,
'mintcream': 0xF5FFFA,
'mistyrose': 0xFFE4E1,
'moccasin': 0xFFE4B5,
'navajowhite': 0xFFDEAD,
8518 'navy': 0x000080,
'oldlace': 0xFDF5E6,
'olive': 0x808000,
'olivedrab': 0x6B8E23,
'orange': 0xFFA500,
'orangered': 0xFF4500,
'orchid': 0xDA70D6,
8519 'palegoldenrod': 0xEEE8AA,
'palegreen': 0x98FB98,
'paleturquoise': 0xAFEEEE,
'palevioletred': 0xDB7093,
'papayawhip': 0xFFEFD5,
'peachpuff': 0xFFDAB9,
8520 'peru': 0xCD853F,
'pink': 0xFFC0CB,
'plum': 0xDDA0DD,
'powderblue': 0xB0E0E6,
'purple': 0x800080,
'rebeccapurple': 0x663399,
'red': 0xFF0000,
'rosybrown': 0xBC8F8F,
8521 'royalblue': 0x4169E1,
'saddlebrown': 0x8B4513,
'salmon': 0xFA8072,
'sandybrown': 0xF4A460,
'seagreen': 0x2E8B57,
'seashell': 0xFFF5EE,
8522 'sienna': 0xA0522D,
'silver': 0xC0C0C0,
'skyblue': 0x87CEEB,
'slateblue': 0x6A5ACD,
'slategray': 0x708090,
'slategrey': 0x708090,
'snow': 0xFFFAFA,
8523 'springgreen': 0x00FF7F,
'steelblue': 0x4682B4,
'tan': 0xD2B48C,
'teal': 0x008080,
'thistle': 0xD8BFD8,
'tomato': 0xFF6347,
'turquoise': 0x40E0D0,
8524 'violet': 0xEE82EE,
'wheat': 0xF5DEB3,
'white': 0xFFFFFF,
'whitesmoke': 0xF5F5F5,
'yellow': 0xFFFF00,
'yellowgreen': 0x9ACD32 };
8526 const _hslA = {
h: 0,
s: 0,
l: 0 };
8527 const _hslB = {
h: 0,
s: 0,
l: 0 };
8529 function hue2rgb(
p,
q,
t ) {
8531 if (
t < 0 )
t += 1;
8532 if (
t > 1 )
t -= 1;
8533 if (
t < 1 / 6 )
return p + (
q -
p ) * 6 *
t;
8534 if (
t < 1 / 2 )
return q;
8535 if (
t < 2 / 3 )
return p + (
q -
p ) * 6 * ( 2 / 3 -
t );
8542 constructor(
r,
g,
b ) {
8544 this.isColor =
true;
8550 return this.
set(
r,
g,
b );
8562 if ( value && value.isColor ) {
8566 }
else if ( typeof value ===
'number' ) {
8568 this.setHex( value );
8570 }
else if ( typeof value ===
'string' ) {
8572 this.setStyle( value );
8578 this.setRGB(
r,
g,
b );
8586 setScalar( scalar ) {
8596 setHex( hex, colorSpace = SRGBColorSpace ) {
8598 hex =
Math.floor( hex );
8600 this.
r = ( hex >> 16 & 255 ) / 255;
8601 this.
g = ( hex >> 8 & 255 ) / 255;
8602 this.
b = ( hex & 255 ) / 255;
8604 ColorManagement.toWorkingColorSpace(
this, colorSpace );
8610 setRGB(
r,
g,
b, colorSpace = ColorManagement.workingColorSpace ) {
8616 ColorManagement.toWorkingColorSpace(
this, colorSpace );
8622 setHSL(
h,
s,
l, colorSpace = ColorManagement.workingColorSpace ) {
8625 h = euclideanModulo(
h, 1 );
8626 s = clamp(
s, 0, 1 );
8627 l = clamp(
l, 0, 1 );
8631 this.
r = this.
g = this.
b =
l;
8635 const p =
l <= 0.5 ?
l * ( 1 +
s ) :
l +
s - (
l *
s );
8636 const q = ( 2 *
l ) -
p;
8638 this.
r = hue2rgb(
q,
p,
h + 1 / 3 );
8639 this.
g = hue2rgb(
q,
p,
h );
8640 this.
b = hue2rgb(
q,
p,
h - 1 / 3 );
8644 ColorManagement.toWorkingColorSpace(
this, colorSpace );
8650 setStyle(
style, colorSpace = SRGBColorSpace ) {
8652 function handleAlpha(
string ) {
8656 if ( parseFloat(
string ) < 1 ) {
8658 console.warn(
'THREE.Color: Alpha component of ' +
style +
' will be ignored.' );
8667 if (
m = /^(\
w+)\(([^\)]*)\)/.exec(
style ) ) {
8672 const name =
m[ 1 ];
8673 const components =
m[ 2 ];
8680 if ( color = /^\
s*(\
d+)\
s*,\
s*(\
d+)\
s*,\
s*(\
d+)\
s*(?:,\
s*(\
d*\.?\
d+)\
s*)?
$/.exec( components ) ) {
8684 handleAlpha( color[ 4 ] );
8687 Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255,
8688 Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255,
8689 Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255,
8695 if ( color = /^\
s*(\
d+)\%\
s*,\
s*(\
d+)\%\
s*,\
s*(\
d+)\%\
s*(?:,\
s*(\
d*\.?\
d+)\
s*)?
$/.exec( components ) ) {
8699 handleAlpha( color[ 4 ] );
8702 Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100,
8703 Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100,
8704 Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100,
8715 if ( color = /^\
s*(\
d*\.?\
d+)\
s*,\
s*(\
d*\.?\
d+)\%\
s*,\
s*(\
d*\.?\
d+)\%\
s*(?:,\
s*(\
d*\.?\
d+)\
s*)?
$/.exec( components ) ) {
8719 handleAlpha( color[ 4 ] );
8722 parseFloat( color[ 1 ] ) / 360,
8723 parseFloat( color[ 2 ] ) / 100,
8724 parseFloat( color[ 3 ] ) / 100,
8734 console.warn(
'THREE.Color: Unknown color model ' +
style );
8738 }
else if (
m = /^\#([
A-Fa-
f\
d]+)
$/.exec(
style ) ) {
8743 const size = hex.length;
8749 parseInt( hex.charAt( 0 ), 16 ) / 15,
8750 parseInt( hex.charAt( 1 ), 16 ) / 15,
8751 parseInt( hex.charAt( 2 ), 16 ) / 15,
8755 }
else if ( size === 6 ) {
8758 return this.setHex( parseInt( hex, 16 ), colorSpace );
8762 console.warn(
'THREE.Color: Invalid hex color ' +
style );
8768 return this.setColorName(
style, colorSpace );
8776 setColorName(
style, colorSpace = SRGBColorSpace ) {
8779 const hex = _colorKeywords[
style.toLowerCase() ];
8784 this.setHex( hex, colorSpace );
8789 console.warn(
'THREE.Color: Unknown color ' +
style );
8799 return new this.constructor( this.
r, this.
g, this.
b );
8813 copySRGBToLinear( color ) {
8815 this.
r = SRGBToLinear( color.r );
8816 this.
g = SRGBToLinear( color.g );
8817 this.
b = SRGBToLinear( color.b );
8823 copyLinearToSRGB( color ) {
8825 this.
r = LinearToSRGB( color.r );
8826 this.
g = LinearToSRGB( color.g );
8827 this.
b = LinearToSRGB( color.b );
8833 convertSRGBToLinear() {
8835 this.copySRGBToLinear(
this );
8841 convertLinearToSRGB() {
8843 this.copyLinearToSRGB(
this );
8849 getHex( colorSpace = SRGBColorSpace ) {
8851 ColorManagement.fromWorkingColorSpace( _color.copy(
this ), colorSpace );
8853 return Math.round( clamp( _color.r * 255, 0, 255 ) ) * 65536 +
Math.round( clamp( _color.g * 255, 0, 255 ) ) * 256 +
Math.round( clamp( _color.b * 255, 0, 255 ) );
8857 getHexString( colorSpace = SRGBColorSpace ) {
8859 return (
'000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 );
8863 getHSL( target, colorSpace = ColorManagement.workingColorSpace ) {
8867 ColorManagement.fromWorkingColorSpace( _color.copy(
this ), colorSpace );
8869 const r = _color.r,
g = _color.g,
b = _color.b;
8874 let hue, saturation;
8875 const lightness = (
min +
max ) / 2.0;
8886 saturation = lightness <= 0.5 ? delta / (
max +
min ) : delta / ( 2 -
max -
min );
8890 case r: hue = (
g -
b ) / delta + (
g <
b ? 6 : 0 );
break;
8891 case g: hue = (
b -
r ) / delta + 2;
break;
8892 case b: hue = (
r -
g ) / delta + 4;
break;
8901 target.s = saturation;
8902 target.l = lightness;
8908 getRGB( target, colorSpace = ColorManagement.workingColorSpace ) {
8910 ColorManagement.fromWorkingColorSpace( _color.copy(
this ), colorSpace );
8912 target.r = _color.r;
8913 target.g = _color.g;
8914 target.b = _color.b;
8920 getStyle( colorSpace = SRGBColorSpace ) {
8922 ColorManagement.fromWorkingColorSpace( _color.copy(
this ), colorSpace );
8924 const r = _color.r,
g = _color.g,
b = _color.b;
8926 if ( colorSpace !== SRGBColorSpace ) {
8929 return `color(
${ colorSpace }
${
r.toFixed( 3 ) }
${
g.toFixed( 3 ) }
${
b.toFixed( 3 ) })`;
8933 return `rgb(
${
Math.round(
r * 255 ) },
${
Math.round(
g * 255 ) },
${
Math.round(
b * 255 ) })`;
8937 offsetHSL(
h,
s,
l ) {
8939 this.getHSL( _hslA );
8941 return this.setHSL( _hslA.h +
h, _hslA.s +
s, _hslA.l +
l );
8955 addColors( color1, color2 ) {
8957 this.
r = color1.r + color2.r;
8958 this.
g = color1.g + color2.g;
8959 this.
b = color1.b + color2.b;
8977 this.
r =
Math.max( 0, this.
r - color.r );
8978 this.
g =
Math.max( 0, this.
g - color.g );
8979 this.
b =
Math.max( 0, this.
b - color.b );
8995 multiplyScalar(
s ) {
9005 lerp( color, alpha ) {
9007 this.
r += ( color.r - this.
r ) * alpha;
9008 this.
g += ( color.g - this.
g ) * alpha;
9009 this.
b += ( color.b - this.
b ) * alpha;
9015 lerpColors( color1, color2, alpha ) {
9017 this.
r = color1.r + ( color2.r - color1.r ) * alpha;
9018 this.
g = color1.g + ( color2.g - color1.g ) * alpha;
9019 this.
b = color1.b + ( color2.b - color1.b ) * alpha;
9025 lerpHSL( color, alpha ) {
9027 this.getHSL( _hslA );
9028 color.getHSL( _hslB );
9030 const h = lerp( _hslA.h, _hslB.h, alpha );
9031 const s = lerp( _hslA.s, _hslB.s, alpha );
9032 const l = lerp( _hslA.l, _hslB.l, alpha );
9034 this.setHSL(
h,
s,
l );
9040 setFromVector3(
v ) {
9052 const r = this.
r,
g = this.
g,
b = this.
b;
9053 const e =
m.elements;
9055 this.
r =
e[ 0 ] *
r +
e[ 3 ] *
g +
e[ 6 ] *
b;
9056 this.
g =
e[ 1 ] *
r +
e[ 4 ] *
g +
e[ 7 ] *
b;
9057 this.
b =
e[ 2 ] *
r +
e[ 5 ] *
g +
e[ 8 ] *
b;
9065 return (
c.r ===
this.r ) && (
c.g === this.
g ) && (
c.b ===
this.b );
9071 this.
r = array[ offset ];
9072 this.
g = array[ offset + 1 ];
9073 this.
b = array[ offset + 2 ];
9079 toArray( array = [], offset = 0 ) {
9081 array[ offset ] = this.
r;
9082 array[ offset + 1 ] = this.
g;
9083 array[ offset + 2 ] = this.
b;
9089 fromBufferAttribute( attribute, index ) {
9091 this.
r = attribute.getX( index );
9092 this.
g = attribute.getY( index );
9093 this.
b = attribute.getZ( index );
9101 return this.getHex();
9105 *[ Symbol.iterator ]() {
9115 const _color =
new Color();
9117 Color.NAMES = _colorKeywords;
9119 let _materialId = 0;
9127 this.isMaterial =
true;
9129 Object.defineProperty(
this,
'id', { value: _materialId ++ } );
9131 this.uuid = generateUUID();
9134 this.type =
'Material';
9138 this.vertexColors =
false;
9141 this.transparent =
false;
9142 this.alphaHash =
false;
9147 this.blendSrcAlpha =
null;
9148 this.blendDstAlpha =
null;
9149 this.blendEquationAlpha =
null;
9150 this.blendColor =
new Color( 0, 0, 0 );
9151 this.blendAlpha = 0;
9153 this.depthFunc = LessEqualDepth;
9154 this.depthTest =
true;
9155 this.depthWrite =
true;
9157 this.stencilWriteMask = 0xff;
9158 this.stencilFunc = AlwaysStencilFunc;
9159 this.stencilRef = 0;
9160 this.stencilFuncMask = 0xff;
9161 this.stencilFail = KeepStencilOp;
9162 this.stencilZFail = KeepStencilOp;
9163 this.stencilZPass = KeepStencilOp;
9164 this.stencilWrite =
false;
9166 this.clippingPlanes =
null;
9167 this.clipIntersection =
false;
9168 this.clipShadows =
false;
9170 this.shadowSide =
null;
9172 this.colorWrite =
true;
9174 this.precision =
null;
9176 this.polygonOffset =
false;
9177 this.polygonOffsetFactor = 0;
9178 this.polygonOffsetUnits = 0;
9180 this.dithering =
false;
9182 this.alphaToCoverage =
false;
9183 this.premultipliedAlpha =
false;
9184 this.forceSinglePass =
false;
9186 this.visible =
true;
9188 this.toneMapped =
true;
9194 this._alphaTest = 0;
9200 return this._alphaTest;
9204 set alphaTest( value ) {
9206 if ( this._alphaTest > 0 !== value > 0 ) {
9212 this._alphaTest = value;
9218 onBeforeRender( ) {}
9220 onBeforeCompile( ) {}
9222 customProgramCacheKey() {
9224 return this.onBeforeCompile.toString();
9228 setValues( values ) {
9232 for (
const key in values ) {
9234 const newValue = values[ key ];
9238 console.warn( `
THREE.Material: parameter
'${ key }' has value of
undefined.` );
9243 const currentValue =
this[ key ];
9247 console.warn( `
THREE.Material:
'${ key }' is not
a property of
THREE.${ this.type }.` );
9252 if ( currentValue && currentValue.isColor ) {
9254 currentValue.set( newValue );
9256 }
else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) {
9258 currentValue.copy( newValue );
9262 this[ key ] = newValue;
9272 const isRootObject = ( meta ===
undefined || typeof meta ===
'string' );
9274 if ( isRootObject ) {
9287 generator:
'Material.toJSON'
9292 data.uuid = this.uuid;
9293 data.type = this.type;
9295 if ( this.name !==
'' ) data.name = this.name;
9297 if ( this.color && this.color.isColor ) data.color = this.color.getHex();
9299 if ( this.roughness !==
undefined ) data.roughness = this.roughness;
9300 if ( this.metalness !==
undefined ) data.metalness = this.metalness;
9302 if ( this.sheen !==
undefined ) data.sheen = this.sheen;
9303 if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex();
9304 if ( this.sheenRoughness !==
undefined ) data.sheenRoughness = this.sheenRoughness;
9305 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex();
9306 if ( this.emissiveIntensity && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity;
9308 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex();
9309 if ( this.specularIntensity !==
undefined ) data.specularIntensity = this.specularIntensity;
9310 if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex();
9311 if ( this.shininess !==
undefined ) data.shininess = this.shininess;
9312 if ( this.clearcoat !==
undefined ) data.clearcoat = this.clearcoat;
9313 if ( this.clearcoatRoughness !==
undefined ) data.clearcoatRoughness = this.clearcoatRoughness;
9315 if ( this.clearcoatMap && this.clearcoatMap.isTexture ) {
9317 data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid;
9321 if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) {
9323 data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid;
9327 if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) {
9329 data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid;
9330 data.clearcoatNormalScale = this.clearcoatNormalScale.toArray();
9334 if ( this.iridescence !==
undefined ) data.iridescence = this.iridescence;
9335 if ( this.iridescenceIOR !==
undefined ) data.iridescenceIOR = this.iridescenceIOR;
9336 if ( this.iridescenceThicknessRange !==
undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange;
9338 if ( this.iridescenceMap && this.iridescenceMap.isTexture ) {
9340 data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid;
9344 if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) {
9346 data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid;
9350 if ( this.anisotropy !==
undefined ) data.anisotropy = this.anisotropy;
9351 if ( this.anisotropyRotation !==
undefined ) data.anisotropyRotation = this.anisotropyRotation;
9353 if ( this.anisotropyMap && this.anisotropyMap.isTexture ) {
9355 data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid;
9359 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid;
9360 if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid;
9361 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid;
9363 if ( this.lightMap && this.lightMap.isTexture ) {
9365 data.lightMap = this.lightMap.toJSON( meta ).uuid;
9366 data.lightMapIntensity = this.lightMapIntensity;
9370 if ( this.aoMap && this.aoMap.isTexture ) {
9372 data.aoMap = this.aoMap.toJSON( meta ).uuid;
9373 data.aoMapIntensity = this.aoMapIntensity;
9377 if ( this.bumpMap && this.bumpMap.isTexture ) {
9379 data.bumpMap = this.bumpMap.toJSON( meta ).uuid;
9380 data.bumpScale = this.bumpScale;
9384 if ( this.normalMap && this.normalMap.isTexture ) {
9386 data.normalMap = this.normalMap.toJSON( meta ).uuid;
9387 data.normalMapType = this.normalMapType;
9388 data.normalScale = this.normalScale.toArray();
9392 if ( this.displacementMap && this.displacementMap.isTexture ) {
9394 data.displacementMap = this.displacementMap.toJSON( meta ).uuid;
9395 data.displacementScale = this.displacementScale;
9396 data.displacementBias = this.displacementBias;
9400 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid;
9401 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid;
9403 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid;
9404 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid;
9405 if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid;
9406 if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid;
9408 if ( this.envMap && this.envMap.isTexture ) {
9410 data.envMap = this.envMap.toJSON( meta ).uuid;
9412 if ( this.combine !==
undefined ) data.combine = this.combine;
9416 if ( this.envMapIntensity !==
undefined ) data.envMapIntensity = this.envMapIntensity;
9417 if ( this.reflectivity !==
undefined ) data.reflectivity = this.reflectivity;
9418 if ( this.refractionRatio !==
undefined ) data.refractionRatio = this.refractionRatio;
9420 if ( this.gradientMap && this.gradientMap.isTexture ) {
9422 data.gradientMap = this.gradientMap.toJSON( meta ).uuid;
9426 if ( this.transmission !==
undefined ) data.transmission = this.transmission;
9427 if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid;
9428 if ( this.thickness !==
undefined ) data.thickness = this.thickness;
9429 if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid;
9430 if ( this.attenuationDistance !==
undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance;
9431 if ( this.attenuationColor !==
undefined ) data.attenuationColor = this.attenuationColor.getHex();
9433 if ( this.size !==
undefined ) data.size = this.size;
9434 if ( this.shadowSide !==
null ) data.shadowSide = this.shadowSide;
9435 if ( this.sizeAttenuation !==
undefined ) data.sizeAttenuation = this.sizeAttenuation;
9437 if ( this.blending !==
NormalBlending ) data.blending = this.blending;
9438 if ( this.side !==
FrontSide ) data.side = this.side;
9439 if ( this.vertexColors ===
true ) data.vertexColors =
true;
9441 if ( this.opacity < 1 ) data.opacity = this.opacity;
9442 if ( this.transparent ===
true ) data.transparent =
true;
9444 if ( this.blendSrc !==
SrcAlphaFactor ) data.blendSrc = this.blendSrc;
9446 if ( this.blendEquation !==
AddEquation ) data.blendEquation = this.blendEquation;
9447 if ( this.blendSrcAlpha !==
null ) data.blendSrcAlpha = this.blendSrcAlpha;
9448 if ( this.blendDstAlpha !==
null ) data.blendDstAlpha = this.blendDstAlpha;
9449 if ( this.blendEquationAlpha !==
null ) data.blendEquationAlpha = this.blendEquationAlpha;
9450 if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex();
9451 if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha;
9453 if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc;
9454 if ( this.depthTest ===
false ) data.depthTest = this.depthTest;
9455 if ( this.depthWrite ===
false ) data.depthWrite = this.depthWrite;
9456 if ( this.colorWrite ===
false ) data.colorWrite = this.colorWrite;
9458 if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask;
9459 if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc;
9460 if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef;
9461 if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask;
9462 if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail;
9463 if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail;
9464 if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass;
9465 if ( this.stencilWrite ===
true ) data.stencilWrite = this.stencilWrite;
9468 if ( this.rotation !==
undefined && this.rotation !== 0 ) data.rotation = this.rotation;
9470 if ( this.polygonOffset ===
true ) data.polygonOffset =
true;
9471 if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor;
9472 if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits;
9474 if ( this.linewidth !==
undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth;
9475 if ( this.dashSize !==
undefined ) data.dashSize = this.dashSize;
9476 if ( this.gapSize !==
undefined ) data.gapSize = this.gapSize;
9477 if ( this.scale !==
undefined ) data.scale = this.scale;
9479 if ( this.dithering ===
true ) data.dithering =
true;
9481 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
9482 if ( this.alphaHash ===
true ) data.alphaHash =
true;
9483 if ( this.alphaToCoverage ===
true ) data.alphaToCoverage =
true;
9484 if ( this.premultipliedAlpha ===
true ) data.premultipliedAlpha =
true;
9485 if ( this.forceSinglePass ===
true ) data.forceSinglePass =
true;
9487 if ( this.wireframe ===
true ) data.wireframe =
true;
9488 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
9489 if ( this.wireframeLinecap !==
'round' ) data.wireframeLinecap = this.wireframeLinecap;
9490 if ( this.wireframeLinejoin !==
'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
9492 if ( this.flatShading ===
true ) data.flatShading =
true;
9494 if ( this.visible ===
false ) data.visible =
false;
9496 if ( this.toneMapped ===
false ) data.toneMapped =
false;
9498 if ( this.fog ===
false ) data.fog =
false;
9500 if ( Object.keys(
this.userData ).length > 0 ) data.userData = this.userData;
9504 function extractFromCache(
cache ) {
9508 for (
const key in
cache ) {
9510 const data =
cache[ key ];
9511 delete data.metadata;
9512 values.push( data );
9520 if ( isRootObject ) {
9522 const textures = extractFromCache( meta.textures );
9523 const images = extractFromCache( meta.images );
9525 if ( textures.length > 0 ) data.textures = textures;
9526 if ( images.length > 0 ) data.images = images;
9536 return new this.constructor().copy(
this );
9542 this.name = source.name;
9544 this.blending = source.blending;
9545 this.side = source.side;
9546 this.vertexColors = source.vertexColors;
9548 this.opacity = source.opacity;
9549 this.transparent = source.transparent;
9551 this.blendSrc = source.blendSrc;
9552 this.blendDst = source.blendDst;
9553 this.blendEquation = source.blendEquation;
9554 this.blendSrcAlpha = source.blendSrcAlpha;
9555 this.blendDstAlpha = source.blendDstAlpha;
9556 this.blendEquationAlpha = source.blendEquationAlpha;
9557 this.blendColor.copy( source.blendColor );
9558 this.blendAlpha = source.blendAlpha;
9560 this.depthFunc = source.depthFunc;
9561 this.depthTest = source.depthTest;
9562 this.depthWrite = source.depthWrite;
9564 this.stencilWriteMask = source.stencilWriteMask;
9565 this.stencilFunc = source.stencilFunc;
9566 this.stencilRef = source.stencilRef;
9567 this.stencilFuncMask = source.stencilFuncMask;
9568 this.stencilFail = source.stencilFail;
9569 this.stencilZFail = source.stencilZFail;
9570 this.stencilZPass = source.stencilZPass;
9571 this.stencilWrite = source.stencilWrite;
9573 const srcPlanes = source.clippingPlanes;
9574 let dstPlanes =
null;
9576 if ( srcPlanes !==
null ) {
9578 const n = srcPlanes.length;
9579 dstPlanes =
new Array(
n );
9581 for ( let
i = 0;
i !==
n; ++
i ) {
9583 dstPlanes[
i ] = srcPlanes[
i ].clone();
9589 this.clippingPlanes = dstPlanes;
9590 this.clipIntersection = source.clipIntersection;
9591 this.clipShadows = source.clipShadows;
9593 this.shadowSide = source.shadowSide;
9595 this.colorWrite = source.colorWrite;
9597 this.precision = source.precision;
9599 this.polygonOffset = source.polygonOffset;
9600 this.polygonOffsetFactor = source.polygonOffsetFactor;
9601 this.polygonOffsetUnits = source.polygonOffsetUnits;
9603 this.dithering = source.dithering;
9605 this.alphaTest = source.alphaTest;
9606 this.alphaHash = source.alphaHash;
9607 this.alphaToCoverage = source.alphaToCoverage;
9608 this.premultipliedAlpha = source.premultipliedAlpha;
9609 this.forceSinglePass = source.forceSinglePass;
9611 this.visible = source.visible;
9613 this.toneMapped = source.toneMapped;
9615 this.userData = JSON.parse( JSON.stringify( source.userData ) );
9623 this.dispatchEvent( { type:
'dispose' } );
9627 set needsUpdate( value ) {
9629 if ( value ===
true ) this.
version ++;
9637 constructor( parameters ) {
9641 this.isMeshBasicMaterial =
true;
9643 this.type =
'MeshBasicMaterial';
9645 this.color =
new Color( 0xffffff );
9649 this.lightMap =
null;
9650 this.lightMapIntensity = 1.0;
9653 this.aoMapIntensity = 1.0;
9655 this.specularMap =
null;
9657 this.alphaMap =
null;
9661 this.reflectivity = 1;
9662 this.refractionRatio = 0.98;
9664 this.wireframe =
false;
9665 this.wireframeLinewidth = 1;
9666 this.wireframeLinecap =
'round';
9667 this.wireframeLinejoin =
'round';
9671 this.setValues( parameters );
9677 super.copy( source );
9679 this.color.copy( source.color );
9681 this.map = source.map;
9683 this.lightMap = source.lightMap;
9684 this.lightMapIntensity = source.lightMapIntensity;
9686 this.aoMap = source.aoMap;
9687 this.aoMapIntensity = source.aoMapIntensity;
9689 this.specularMap = source.specularMap;
9691 this.alphaMap = source.alphaMap;
9693 this.envMap = source.envMap;
9694 this.combine = source.combine;
9695 this.reflectivity = source.reflectivity;
9696 this.refractionRatio = source.refractionRatio;
9698 this.wireframe = source.wireframe;
9699 this.wireframeLinewidth = source.wireframeLinewidth;
9700 this.wireframeLinecap = source.wireframeLinecap;
9701 this.wireframeLinejoin = source.wireframeLinejoin;
9703 this.fog = source.fog;
9713 const _tables = _generateTables();
9715 function _generateTables() {
9719 const buffer =
new ArrayBuffer( 4 );
9726 for ( let
i = 0;
i < 256; ++
i ) {
9734 baseTable[
i ] = 0x0000;
9735 baseTable[
i | 0x100 ] = 0x8000;
9736 shiftTable[
i ] = 24;
9737 shiftTable[
i | 0x100 ] = 24;
9741 }
else if (
e < - 14 ) {
9743 baseTable[
i ] = 0x0400 >> ( -
e - 14 );
9744 baseTable[
i | 0x100 ] = ( 0x0400 >> ( -
e - 14 ) ) | 0x8000;
9745 shiftTable[
i ] = -
e - 1;
9746 shiftTable[
i | 0x100 ] = -
e - 1;
9750 }
else if (
e <= 15 ) {
9752 baseTable[
i ] = (
e + 15 ) << 10;
9753 baseTable[
i | 0x100 ] = ( (
e + 15 ) << 10 ) | 0x8000;
9754 shiftTable[
i ] = 13;
9755 shiftTable[
i | 0x100 ] = 13;
9759 }
else if (
e < 128 ) {
9761 baseTable[
i ] = 0x7c00;
9762 baseTable[
i | 0x100 ] = 0xfc00;
9763 shiftTable[
i ] = 24;
9764 shiftTable[
i | 0x100 ] = 24;
9770 baseTable[
i ] = 0x7c00;
9771 baseTable[
i | 0x100 ] = 0xfc00;
9772 shiftTable[
i ] = 13;
9773 shiftTable[
i | 0x100 ] = 13;
9785 for ( let
i = 1;
i < 1024; ++
i ) {
9791 while ( (
m & 0x00800000 ) === 0 ) {
9801 mantissaTable[
i ] =
m |
e;
9805 for ( let
i = 1024;
i < 2048; ++
i ) {
9807 mantissaTable[
i ] = 0x38000000 + ( (
i - 1024 ) << 13 );
9811 for ( let
i = 1;
i < 31; ++
i ) {
9813 exponentTable[
i ] =
i << 23;
9817 exponentTable[ 31 ] = 0x47800000;
9818 exponentTable[ 32 ] = 0x80000000;
9820 for ( let
i = 33;
i < 63; ++
i ) {
9822 exponentTable[
i ] = 0x80000000 + ( (
i - 32 ) << 23 );
9826 exponentTable[ 63 ] = 0xc7800000;
9828 for ( let
i = 1;
i < 64; ++
i ) {
9832 offsetTable[
i ] = 1024;
9839 floatView: floatView,
9840 uint32View: uint32View,
9841 baseTable: baseTable,
9842 shiftTable: shiftTable,
9843 mantissaTable: mantissaTable,
9844 exponentTable: exponentTable,
9845 offsetTable: offsetTable
9852 function toHalfFloat( val ) {
9854 if (
Math.abs( val ) > 65504 ) console.warn(
'THREE.DataUtils.toHalfFloat(): Value out of range.' );
9856 val = clamp( val, - 65504, 65504 );
9858 _tables.floatView[ 0 ] = val;
9859 const f = _tables.uint32View[ 0 ];
9860 const e = (
f >> 23 ) & 0x1ff;
9861 return _tables.baseTable[
e ] + ( (
f & 0x007fffff ) >> _tables.shiftTable[
e ] );
9867 function fromHalfFloat( val ) {
9869 const m = val >> 10;
9870 _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[
m ] + ( val & 0x3ff ) ] + _tables.exponentTable[
m ];
9871 return _tables.floatView[ 0 ];
9876 toHalfFloat: toHalfFloat,
9877 fromHalfFloat: fromHalfFloat,
9880 const _vector$9 =
new Vector3();
9881 const _vector2$1 =
new Vector2();
9885 constructor( array, itemSize, normalized =
false ) {
9887 if (
Array.isArray( array ) ) {
9889 throw new TypeError(
'THREE.BufferAttribute: array should be a Typed Array.' );
9893 this.isBufferAttribute =
true;
9898 this.itemSize = itemSize;
9899 this.count = array !==
undefined ? array.length / itemSize : 0;
9900 this.normalized = normalized;
9902 this.usage = StaticDrawUsage;
9903 this._updateRange = { offset: 0, count: - 1 };
9904 this.updateRanges = [];
9911 onUploadCallback() {}
9913 set needsUpdate( value ) {
9915 if ( value ===
true ) this.
version ++;
9921 console.warn(
'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' );
9922 return this._updateRange;
9934 addUpdateRange( start, count ) {
9936 this.updateRanges.push( { start, count } );
9940 clearUpdateRanges() {
9942 this.updateRanges.length = 0;
9948 this.name = source.name;
9949 this.array =
new source.array.constructor( source.array );
9950 this.itemSize = source.itemSize;
9951 this.count = source.count;
9952 this.normalized = source.normalized;
9954 this.usage = source.usage;
9955 this.gpuType = source.gpuType;
9961 copyAt( index1, attribute, index2 ) {
9963 index1 *= this.itemSize;
9964 index2 *= attribute.itemSize;
9966 for ( let
i = 0,
l = this.itemSize;
i <
l;
i ++ ) {
9968 this.array[ index1 +
i ] = attribute.array[ index2 +
i ];
9976 copyArray( array ) {
9978 this.array.set( array );
9986 if ( this.itemSize === 2 ) {
9988 for ( let
i = 0,
l = this.count;
i <
l;
i ++ ) {
9990 _vector2$1.fromBufferAttribute(
this,
i );
9991 _vector2$1.applyMatrix3(
m );
9993 this.setXY(
i, _vector2$1.x, _vector2$1.y );
9997 }
else if ( this.itemSize === 3 ) {
9999 for ( let
i = 0,
l = this.count;
i <
l;
i ++ ) {
10001 _vector$9.fromBufferAttribute(
this,
i );
10002 _vector$9.applyMatrix3(
m );
10004 this.setXYZ(
i, _vector$9.x, _vector$9.y, _vector$9.z );
10014 applyMatrix4(
m ) {
10016 for ( let
i = 0,
l = this.count;
i <
l;
i ++ ) {
10018 _vector$9.fromBufferAttribute(
this,
i );
10020 _vector$9.applyMatrix4(
m );
10022 this.setXYZ(
i, _vector$9.x, _vector$9.y, _vector$9.z );
10030 applyNormalMatrix(
m ) {
10032 for ( let
i = 0,
l = this.count;
i <
l;
i ++ ) {
10034 _vector$9.fromBufferAttribute(
this,
i );
10036 _vector$9.applyNormalMatrix(
m );
10038 this.setXYZ(
i, _vector$9.x, _vector$9.y, _vector$9.z );
10046 transformDirection(
m ) {
10048 for ( let
i = 0,
l = this.count;
i <
l;
i ++ ) {
10050 _vector$9.fromBufferAttribute(
this,
i );
10052 _vector$9.transformDirection(
m );
10054 this.setXYZ(
i, _vector$9.x, _vector$9.y, _vector$9.z );
10062 set( value, offset = 0 ) {
10065 this.array.set( value, offset );
10071 getComponent( index, component ) {
10073 let value = this.array[ index * this.itemSize + component ];
10075 if ( this.normalized ) value = denormalize( value, this.array );
10081 setComponent( index, component, value ) {
10083 if ( this.normalized ) value = normalize( value, this.array );
10085 this.array[ index * this.itemSize + component ] = value;
10093 let
x = this.array[ index * this.itemSize ];
10095 if ( this.normalized )
x = denormalize(
x, this.array );
10103 if ( this.normalized )
x = normalize(
x, this.array );
10105 this.array[ index * this.itemSize ] =
x;
10113 let
y = this.array[ index * this.itemSize + 1 ];
10115 if ( this.normalized )
y = denormalize(
y, this.array );
10123 if ( this.normalized )
y = normalize(
y, this.array );
10125 this.array[ index * this.itemSize + 1 ] =
y;
10133 let
z = this.array[ index * this.itemSize + 2 ];
10135 if ( this.normalized )
z = denormalize(
z, this.array );
10143 if ( this.normalized )
z = normalize(
z, this.array );
10145 this.array[ index * this.itemSize + 2 ] =
z;
10153 let
w = this.array[ index * this.itemSize + 3 ];
10155 if ( this.normalized )
w = denormalize(
w, this.array );
10163 if ( this.normalized )
w = normalize(
w, this.array );
10165 this.array[ index * this.itemSize + 3 ] =
w;
10171 setXY( index,
x,
y ) {
10173 index *= this.itemSize;
10175 if ( this.normalized ) {
10177 x = normalize(
x, this.array );
10178 y = normalize(
y, this.array );
10182 this.array[ index + 0 ] =
x;
10183 this.array[ index + 1 ] =
y;
10189 setXYZ( index,
x,
y,
z ) {
10191 index *= this.itemSize;
10193 if ( this.normalized ) {
10195 x = normalize(
x, this.array );
10196 y = normalize(
y, this.array );
10197 z = normalize(
z, this.array );
10201 this.array[ index + 0 ] =
x;
10202 this.array[ index + 1 ] =
y;
10203 this.array[ index + 2 ] =
z;
10209 setXYZW( index,
x,
y,
z,
w ) {
10211 index *= this.itemSize;
10213 if ( this.normalized ) {
10215 x = normalize(
x, this.array );
10216 y = normalize(
y, this.array );
10217 z = normalize(
z, this.array );
10218 w = normalize(
w, this.array );
10222 this.array[ index + 0 ] =
x;
10223 this.array[ index + 1 ] =
y;
10224 this.array[ index + 2 ] =
z;
10225 this.array[ index + 3 ] =
w;
10231 onUpload( callback ) {
10233 this.onUploadCallback = callback;
10241 return new this.constructor( this.array, this.itemSize ).copy(
this );
10248 itemSize: this.itemSize,
10249 type: this.array.constructor.name,
10250 array:
Array.from( this.array ),
10251 normalized: this.normalized
10254 if ( this.name !==
'' ) data.name = this.name;
10255 if ( this.usage !== StaticDrawUsage ) data.usage = this.usage;
10267 constructor( array, itemSize, normalized ) {
10269 super(
new Int8Array( array ), itemSize, normalized );
10277 constructor( array, itemSize, normalized ) {
10279 super(
new Uint8Array( array ), itemSize, normalized );
10287 constructor( array, itemSize, normalized ) {
10297 constructor( array, itemSize, normalized ) {
10299 super(
new Int16Array( array ), itemSize, normalized );
10307 constructor( array, itemSize, normalized ) {
10309 super(
new Uint16Array( array ), itemSize, normalized );
10317 constructor( array, itemSize, normalized ) {
10319 super(
new Int32Array( array ), itemSize, normalized );
10327 constructor( array, itemSize, normalized ) {
10329 super(
new Uint32Array( array ), itemSize, normalized );
10337 constructor( array, itemSize, normalized ) {
10339 super(
new Uint16Array( array ), itemSize, normalized );
10341 this.isFloat16BufferAttribute =
true;
10347 let
x = fromHalfFloat( this.array[ index * this.itemSize ] );
10349 if ( this.normalized )
x = denormalize(
x, this.array );
10357 if ( this.normalized )
x = normalize(
x, this.array );
10359 this.array[ index * this.itemSize ] = toHalfFloat(
x );
10367 let
y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] );
10369 if ( this.normalized )
y = denormalize(
y, this.array );
10377 if ( this.normalized )
y = normalize(
y, this.array );
10379 this.array[ index * this.itemSize + 1 ] = toHalfFloat(
y );
10387 let
z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] );
10389 if ( this.normalized )
z = denormalize(
z, this.array );
10397 if ( this.normalized )
z = normalize(
z, this.array );
10399 this.array[ index * this.itemSize + 2 ] = toHalfFloat(
z );
10407 let
w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] );
10409 if ( this.normalized )
w = denormalize(
w, this.array );
10417 if ( this.normalized )
w = normalize(
w, this.array );
10419 this.array[ index * this.itemSize + 3 ] = toHalfFloat(
w );
10425 setXY( index,
x,
y ) {
10427 index *= this.itemSize;
10429 if ( this.normalized ) {
10431 x = normalize(
x, this.array );
10432 y = normalize(
y, this.array );
10436 this.array[ index + 0 ] = toHalfFloat(
x );
10437 this.array[ index + 1 ] = toHalfFloat(
y );
10443 setXYZ( index,
x,
y,
z ) {
10445 index *= this.itemSize;
10447 if ( this.normalized ) {
10449 x = normalize(
x, this.array );
10450 y = normalize(
y, this.array );
10451 z = normalize(
z, this.array );
10455 this.array[ index + 0 ] = toHalfFloat(
x );
10456 this.array[ index + 1 ] = toHalfFloat(
y );
10457 this.array[ index + 2 ] = toHalfFloat(
z );
10463 setXYZW( index,
x,
y,
z,
w ) {
10465 index *= this.itemSize;
10467 if ( this.normalized ) {
10469 x = normalize(
x, this.array );
10470 y = normalize(
y, this.array );
10471 z = normalize(
z, this.array );
10472 w = normalize(
w, this.array );
10476 this.array[ index + 0 ] = toHalfFloat(
x );
10477 this.array[ index + 1 ] = toHalfFloat(
y );
10478 this.array[ index + 2 ] = toHalfFloat(
z );
10479 this.array[ index + 3 ] = toHalfFloat(
w );
10490 constructor( array, itemSize, normalized ) {
10492 super(
new Float32Array( array ), itemSize, normalized );
10500 constructor( array, itemSize, normalized ) {
10502 super(
new Float64Array( array ), itemSize, normalized );
10512 const _offset =
new Vector3();
10513 const _box$2 =
new Box3();
10514 const _boxMorphTargets =
new Box3();
10515 const _vector$8 =
new Vector3();
10523 this.isBufferGeometry =
true;
10525 Object.defineProperty(
this,
'id', { value: _id$2 ++ } );
10527 this.uuid = generateUUID();
10530 this.type =
'BufferGeometry';
10533 this.attributes = {};
10535 this.morphAttributes = {};
10536 this.morphTargetsRelative =
false;
10540 this.boundingBox =
null;
10541 this.boundingSphere =
null;
10543 this.drawRange = { start: 0, count: Infinity };
10545 this.userData = {};
10555 setIndex( index ) {
10557 if (
Array.isArray( index ) ) {
10559 this.index =
new ( arrayNeedsUint32( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 );
10563 this.index = index;
10571 getAttribute( name ) {
10573 return this.attributes[ name ];
10577 setAttribute( name, attribute ) {
10579 this.attributes[ name ] = attribute;
10585 deleteAttribute( name ) {
10587 delete this.attributes[ name ];
10593 hasAttribute( name ) {
10595 return this.attributes[ name ] !==
undefined;
10599 addGroup( start, count, materialIndex = 0 ) {
10601 this.groups.push( {
10605 materialIndex: materialIndex
10617 setDrawRange( start, count ) {
10619 this.drawRange.start = start;
10620 this.drawRange.count = count;
10624 applyMatrix4( matrix ) {
10626 const position = this.attributes.position;
10636 const normal = this.attributes.normal;
10640 const normalMatrix =
new Matrix3().getNormalMatrix( matrix );
10642 normal.applyNormalMatrix( normalMatrix );
10644 normal.needsUpdate =
true;
10648 const tangent = this.attributes.tangent;
10652 tangent.transformDirection( matrix );
10654 tangent.needsUpdate =
true;
10658 if ( this.boundingBox !==
null ) {
10660 this.computeBoundingBox();
10664 if ( this.boundingSphere !==
null ) {
10666 this.computeBoundingSphere();
10674 applyQuaternion(
q ) {
10676 _m1.makeRotationFromQuaternion(
q );
10678 this.applyMatrix4( _m1 );
10688 _m1.makeRotationX( angle );
10690 this.applyMatrix4( _m1 );
10700 _m1.makeRotationY( angle );
10702 this.applyMatrix4( _m1 );
10712 _m1.makeRotationZ( angle );
10714 this.applyMatrix4( _m1 );
10720 translate(
x,
y,
z ) {
10724 _m1.makeTranslation(
x,
y,
z );
10726 this.applyMatrix4( _m1 );
10736 _m1.makeScale(
x,
y,
z );
10738 this.applyMatrix4( _m1 );
10746 _obj.lookAt( vector );
10748 _obj.updateMatrix();
10750 this.applyMatrix4( _obj.matrix );
10758 this.computeBoundingBox();
10760 this.boundingBox.getCenter( _offset ).negate();
10762 this.translate( _offset.x, _offset.y, _offset.z );
10768 setFromPoints( points ) {
10772 for ( let
i = 0,
l = points.length;
i <
l;
i ++ ) {
10774 const point = points[
i ];
10775 position.push( point.x, point.y, point.z || 0 );
10779 this.setAttribute(
'position',
new Float32BufferAttribute(
position, 3 ) );
10785 computeBoundingBox() {
10787 if ( this.boundingBox ===
null ) {
10789 this.boundingBox =
new Box3();
10793 const position = this.attributes.position;
10794 const morphAttributesPosition = this.morphAttributes.position;
10798 console.error(
'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box. Alternatively set "mesh.frustumCulled" to "false".',
this );
10800 this.boundingBox.set(
10801 new Vector3( - Infinity, - Infinity, - Infinity ),
10802 new Vector3( + Infinity, + Infinity, + Infinity )
10811 this.boundingBox.setFromBufferAttribute(
position );
10815 if ( morphAttributesPosition ) {
10817 for ( let
i = 0, il = morphAttributesPosition.length;
i < il;
i ++ ) {
10819 const morphAttribute = morphAttributesPosition[
i ];
10820 _box$2.setFromBufferAttribute( morphAttribute );
10822 if ( this.morphTargetsRelative ) {
10824 _vector$8.addVectors( this.boundingBox.min, _box$2.min );
10825 this.boundingBox.expandByPoint( _vector$8 );
10827 _vector$8.addVectors( this.boundingBox.max, _box$2.max );
10828 this.boundingBox.expandByPoint( _vector$8 );
10832 this.boundingBox.expandByPoint( _box$2.min );
10833 this.boundingBox.expandByPoint( _box$2.max );
10843 this.boundingBox.makeEmpty();
10847 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) {
10849 console.error(
'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.',
this );
10855 computeBoundingSphere() {
10857 if ( this.boundingSphere ===
null ) {
10859 this.boundingSphere =
new Sphere();
10863 const position = this.attributes.position;
10864 const morphAttributesPosition = this.morphAttributes.position;
10868 console.error(
'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere. Alternatively set "mesh.frustumCulled" to "false".',
this );
10870 this.boundingSphere.set(
new Vector3(), Infinity );
10880 const center = this.boundingSphere.center;
10882 _box$2.setFromBufferAttribute(
position );
10886 if ( morphAttributesPosition ) {
10888 for ( let
i = 0, il = morphAttributesPosition.length;
i < il;
i ++ ) {
10890 const morphAttribute = morphAttributesPosition[
i ];
10891 _boxMorphTargets.setFromBufferAttribute( morphAttribute );
10893 if ( this.morphTargetsRelative ) {
10895 _vector$8.addVectors( _box$2.min, _boxMorphTargets.min );
10896 _box$2.expandByPoint( _vector$8 );
10898 _vector$8.addVectors( _box$2.max, _boxMorphTargets.max );
10899 _box$2.expandByPoint( _vector$8 );
10903 _box$2.expandByPoint( _boxMorphTargets.min );
10904 _box$2.expandByPoint( _boxMorphTargets.max );
10912 _box$2.getCenter( center );
10917 let maxRadiusSq = 0;
10919 for ( let
i = 0, il =
position.count;
i < il;
i ++ ) {
10921 _vector$8.fromBufferAttribute(
position,
i );
10923 maxRadiusSq =
Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
10929 if ( morphAttributesPosition ) {
10931 for ( let
i = 0, il = morphAttributesPosition.length;
i < il;
i ++ ) {
10933 const morphAttribute = morphAttributesPosition[
i ];
10934 const morphTargetsRelative = this.morphTargetsRelative;
10936 for ( let
j = 0, jl = morphAttribute.count;
j < jl;
j ++ ) {
10938 _vector$8.fromBufferAttribute( morphAttribute,
j );
10940 if ( morphTargetsRelative ) {
10942 _offset.fromBufferAttribute(
position,
j );
10943 _vector$8.add( _offset );
10947 maxRadiusSq =
Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) );
10955 this.boundingSphere.radius =
Math.sqrt( maxRadiusSq );
10957 if ( isNaN( this.boundingSphere.radius ) ) {
10959 console.error(
'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.',
this );
10967 computeTangents() {
10969 const index = this.index;
10970 const attributes = this.attributes;
10975 if ( index ===
null ||
10980 console.error(
'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' );
10985 const indices = index.array;
10986 const positions = attributes.position.array;
10987 const normals = attributes.normal.array;
10988 const uvs = attributes.uv.array;
10990 const nVertices = positions.length / 3;
10992 if ( this.hasAttribute(
'tangent' ) ===
false ) {
10998 const tangents = this.getAttribute(
'tangent' ).array;
11000 const tan1 = [], tan2 = [];
11002 for ( let
i = 0;
i < nVertices;
i ++ ) {
11020 function handleTriangle(
a,
b,
c ) {
11022 vA.fromArray( positions,
a * 3 );
11023 vB.fromArray( positions,
b * 3 );
11024 vC.fromArray( positions,
c * 3 );
11026 uvA.fromArray( uvs,
a * 2 );
11027 uvB.fromArray( uvs,
b * 2 );
11028 uvC.fromArray( uvs,
c * 2 );
11036 const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y );
11040 if ( ! isFinite(
r ) )
return;
11042 sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar(
r );
11043 tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar(
r );
11045 tan1[
a ].add( sdir );
11046 tan1[
b ].add( sdir );
11047 tan1[
c ].add( sdir );
11049 tan2[
a ].add( tdir );
11050 tan2[
b ].add( tdir );
11051 tan2[
c ].add( tdir );
11055 let groups = this.groups;
11057 if ( groups.length === 0 ) {
11061 count: indices.length
11066 for ( let
i = 0, il = groups.length;
i < il; ++
i ) {
11068 const group = groups[
i ];
11070 const start = group.start;
11071 const count = group.count;
11073 for ( let
j = start, jl = start + count;
j < jl;
j += 3 ) {
11088 function handleVertex(
v ) {
11090 n.fromArray( normals,
v * 3 );
11093 const t = tan1[
v ];
11098 tmp.sub(
n.multiplyScalar(
n.dot(
t ) ) ).normalize();
11102 tmp2.crossVectors( n2,
t );
11103 const test = tmp2.dot( tan2[
v ] );
11104 const w = ( test < 0.0 ) ? - 1.0 : 1.0;
11106 tangents[
v * 4 ] = tmp.x;
11107 tangents[
v * 4 + 1 ] = tmp.y;
11108 tangents[
v * 4 + 2 ] = tmp.z;
11109 tangents[
v * 4 + 3 ] =
w;
11113 for ( let
i = 0, il = groups.length;
i < il; ++
i ) {
11115 const group = groups[
i ];
11117 const start = group.start;
11118 const count = group.count;
11120 for ( let
j = start, jl = start + count;
j < jl;
j += 3 ) {
11122 handleVertex( indices[
j + 0 ] );
11123 handleVertex( indices[
j + 1 ] );
11124 handleVertex( indices[
j + 2 ] );
11132 computeVertexNormals() {
11134 const index = this.index;
11135 const positionAttribute = this.getAttribute(
'position' );
11137 if ( positionAttribute !==
undefined ) {
11139 let normalAttribute = this.getAttribute(
'normal' );
11144 this.setAttribute(
'normal', normalAttribute );
11150 for ( let
i = 0, il = normalAttribute.count;
i < il;
i ++ ) {
11152 normalAttribute.setXYZ(
i, 0, 0, 0 );
11166 for ( let
i = 0, il = index.count;
i < il;
i += 3 ) {
11168 const vA = index.getX(
i + 0 );
11169 const vB = index.getX(
i + 1 );
11170 const vC = index.getX(
i + 2 );
11172 pA.fromBufferAttribute( positionAttribute, vA );
11173 pB.fromBufferAttribute( positionAttribute, vB );
11174 pC.fromBufferAttribute( positionAttribute, vC );
11176 cb.subVectors( pC, pB );
11177 ab.subVectors( pA, pB );
11180 nA.fromBufferAttribute( normalAttribute, vA );
11181 nB.fromBufferAttribute( normalAttribute, vB );
11182 nC.fromBufferAttribute( normalAttribute, vC );
11188 normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z );
11189 normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z );
11190 normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z );
11198 for ( let
i = 0, il = positionAttribute.count;
i < il;
i += 3 ) {
11200 pA.fromBufferAttribute( positionAttribute,
i + 0 );
11201 pB.fromBufferAttribute( positionAttribute,
i + 1 );
11202 pC.fromBufferAttribute( positionAttribute,
i + 2 );
11204 cb.subVectors( pC, pB );
11205 ab.subVectors( pA, pB );
11208 normalAttribute.setXYZ(
i + 0, cb.x, cb.y, cb.z );
11209 normalAttribute.setXYZ(
i + 1, cb.x, cb.y, cb.z );
11210 normalAttribute.setXYZ(
i + 2, cb.x, cb.y, cb.z );
11216 this.normalizeNormals();
11218 normalAttribute.needsUpdate =
true;
11224 normalizeNormals() {
11226 const normals = this.attributes.normal;
11228 for ( let
i = 0, il = normals.count;
i < il;
i ++ ) {
11230 _vector$8.fromBufferAttribute( normals,
i );
11232 _vector$8.normalize();
11234 normals.setXYZ(
i, _vector$8.x, _vector$8.y, _vector$8.z );
11242 function convertBufferAttribute( attribute, indices ) {
11244 const array = attribute.array;
11245 const itemSize = attribute.itemSize;
11246 const normalized = attribute.normalized;
11248 const array2 =
new array.constructor( indices.length * itemSize );
11250 let index = 0, index2 = 0;
11252 for ( let
i = 0,
l = indices.length;
i <
l;
i ++ ) {
11254 if ( attribute.isInterleavedBufferAttribute ) {
11256 index = indices[
i ] * attribute.data.stride + attribute.offset;
11260 index = indices[
i ] * itemSize;
11264 for ( let
j = 0;
j < itemSize;
j ++ ) {
11266 array2[ index2 ++ ] = array[ index ++ ];
11278 if ( this.index ===
null ) {
11280 console.warn(
'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' );
11287 const indices = this.index.array;
11288 const attributes = this.attributes;
11292 for (
const name in attributes ) {
11294 const attribute = attributes[ name ];
11296 const newAttribute = convertBufferAttribute( attribute, indices );
11298 geometry2.setAttribute( name, newAttribute );
11304 const morphAttributes = this.morphAttributes;
11306 for (
const name in morphAttributes ) {
11308 const morphArray = [];
11309 const morphAttribute = morphAttributes[ name ];
11311 for ( let
i = 0, il = morphAttribute.length;
i < il;
i ++ ) {
11313 const attribute = morphAttribute[
i ];
11315 const newAttribute = convertBufferAttribute( attribute, indices );
11317 morphArray.push( newAttribute );
11321 geometry2.morphAttributes[ name ] = morphArray;
11325 geometry2.morphTargetsRelative = this.morphTargetsRelative;
11329 const groups = this.groups;
11331 for ( let
i = 0,
l = groups.length;
i <
l;
i ++ ) {
11333 const group = groups[
i ];
11334 geometry2.addGroup( group.start, group.count, group.materialIndex );
11347 type:
'BufferGeometry',
11348 generator:
'BufferGeometry.toJSON'
11354 data.uuid = this.uuid;
11355 data.type = this.type;
11356 if ( this.name !==
'' ) data.name = this.name;
11357 if ( Object.keys(
this.userData ).length > 0 ) data.userData = this.userData;
11361 const parameters = this.parameters;
11363 for (
const key in parameters ) {
11365 if ( parameters[ key ] !==
undefined ) data[ key ] = parameters[ key ];
11375 data.data = { attributes: {} };
11377 const index = this.index;
11379 if ( index !==
null ) {
11381 data.data.index = {
11382 type: index.array.constructor.name,
11383 array:
Array.prototype.slice.call( index.array )
11388 const attributes = this.attributes;
11390 for (
const key in attributes ) {
11392 const attribute = attributes[ key ];
11394 data.data.attributes[ key ] = attribute.toJSON( data.data );
11398 const morphAttributes = {};
11399 let hasMorphAttributes =
false;
11401 for (
const key in this.morphAttributes ) {
11403 const attributeArray = this.morphAttributes[ key ];
11407 for ( let
i = 0, il = attributeArray.length;
i < il;
i ++ ) {
11409 const attribute = attributeArray[
i ];
11411 array.push( attribute.toJSON( data.data ) );
11415 if ( array.length > 0 ) {
11417 morphAttributes[ key ] = array;
11419 hasMorphAttributes =
true;
11425 if ( hasMorphAttributes ) {
11427 data.data.morphAttributes = morphAttributes;
11428 data.data.morphTargetsRelative = this.morphTargetsRelative;
11432 const groups = this.groups;
11434 if ( groups.length > 0 ) {
11436 data.data.groups = JSON.parse( JSON.stringify( groups ) );
11440 const boundingSphere = this.boundingSphere;
11442 if ( boundingSphere !==
null ) {
11444 data.data.boundingSphere = {
11445 center: boundingSphere.center.toArray(),
11446 radius: boundingSphere.radius
11457 return new this.constructor().copy(
this );
11466 this.attributes = {};
11467 this.morphAttributes = {};
11469 this.boundingBox =
null;
11470 this.boundingSphere =
null;
11478 this.name = source.name;
11482 const index = source.index;
11484 if ( index !==
null ) {
11486 this.setIndex( index.clone( data ) );
11492 const attributes = source.attributes;
11494 for (
const name in attributes ) {
11496 const attribute = attributes[ name ];
11497 this.setAttribute( name, attribute.clone( data ) );
11503 const morphAttributes = source.morphAttributes;
11505 for (
const name in morphAttributes ) {
11508 const morphAttribute = morphAttributes[ name ];
11510 for ( let
i = 0,
l = morphAttribute.length;
i <
l;
i ++ ) {
11512 array.push( morphAttribute[
i ].
clone( data ) );
11516 this.morphAttributes[ name ] = array;
11520 this.morphTargetsRelative = source.morphTargetsRelative;
11524 const groups = source.groups;
11526 for ( let
i = 0,
l = groups.length;
i <
l;
i ++ ) {
11528 const group = groups[
i ];
11529 this.addGroup( group.start, group.count, group.materialIndex );
11535 const boundingBox = source.boundingBox;
11537 if ( boundingBox !==
null ) {
11539 this.boundingBox = boundingBox.clone();
11545 const boundingSphere = source.boundingSphere;
11547 if ( boundingSphere !==
null ) {
11549 this.boundingSphere = boundingSphere.clone();
11555 this.drawRange.start = source.drawRange.start;
11556 this.drawRange.count = source.drawRange.count;
11560 this.userData = source.userData;
11568 this.dispatchEvent( { type:
'dispose' } );
11574 const _inverseMatrix$3 =
new Matrix4();
11575 const _ray$3 =
new Ray();
11576 const _sphere$6 =
new Sphere();
11577 const _sphereHitAt =
new Vector3();
11583 const _tempA =
new Vector3();
11584 const _morphA =
new Vector3();
11586 const _uvA$1 =
new Vector2();
11587 const _uvB$1 =
new Vector2();
11588 const _uvC$1 =
new Vector2();
11590 const _normalA =
new Vector3();
11591 const _normalB =
new Vector3();
11592 const _normalC =
new Vector3();
11594 const _intersectionPoint =
new Vector3();
11595 const _intersectionPointWorld =
new Vector3();
11603 this.isMesh =
true;
11605 this.type =
'Mesh';
11607 this.geometry = geometry;
11608 this.material = material;
11614 copy( source, recursive ) {
11616 super.copy( source, recursive );
11618 if ( source.morphTargetInfluences !==
undefined ) {
11620 this.morphTargetInfluences = source.morphTargetInfluences.slice();
11624 if ( source.morphTargetDictionary !==
undefined ) {
11626 this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary );
11630 this.material =
Array.isArray( source.material ) ? source.material.slice() : source.material;
11631 this.geometry = source.geometry;
11639 const geometry = this.geometry;
11641 const morphAttributes = geometry.morphAttributes;
11642 const keys = Object.keys( morphAttributes );
11644 if ( keys.length > 0 ) {
11646 const morphAttribute = morphAttributes[ keys[ 0 ] ];
11650 this.morphTargetInfluences = [];
11651 this.morphTargetDictionary = {};
11653 for ( let
m = 0, ml = morphAttribute.length;
m < ml;
m ++ ) {
11655 const name = morphAttribute[
m ].name ||
String(
m );
11657 this.morphTargetInfluences.push( 0 );
11658 this.morphTargetDictionary[ name ] =
m;
11668 getVertexPosition( index, target ) {
11670 const geometry = this.geometry;
11671 const position = geometry.attributes.position;
11672 const morphPosition = geometry.morphAttributes.position;
11673 const morphTargetsRelative = geometry.morphTargetsRelative;
11675 target.fromBufferAttribute(
position, index );
11677 const morphInfluences = this.morphTargetInfluences;
11679 if ( morphPosition && morphInfluences ) {
11681 _morphA.set( 0, 0, 0 );
11683 for ( let
i = 0, il = morphPosition.length;
i < il;
i ++ ) {
11685 const influence = morphInfluences[
i ];
11686 const morphAttribute = morphPosition[
i ];
11688 if ( influence === 0 )
continue;
11690 _tempA.fromBufferAttribute( morphAttribute, index );
11692 if ( morphTargetsRelative ) {
11694 _morphA.addScaledVector( _tempA, influence );
11698 _morphA.addScaledVector( _tempA.sub( target ), influence );
11704 target.add( _morphA );
11712 raycast( raycaster, intersects ) {
11714 const geometry = this.geometry;
11715 const material = this.material;
11716 const matrixWorld = this.matrixWorld;
11722 if ( geometry.boundingSphere ===
null ) geometry.computeBoundingSphere();
11724 _sphere$6.copy( geometry.boundingSphere );
11725 _sphere$6.applyMatrix4( matrixWorld );
11729 _ray$3.copy( raycaster.ray ).recast( raycaster.near );
11731 if ( _sphere$6.containsPoint( _ray$3.origin ) ===
false ) {
11733 if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) ===
null )
return;
11735 if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 )
return;
11741 _inverseMatrix$3.copy( matrixWorld ).invert();
11742 _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 );
11746 if ( geometry.boundingBox !==
null ) {
11748 if ( _ray$3.intersectsBox( geometry.boundingBox ) ===
false )
return;
11754 this._computeIntersections( raycaster, intersects, _ray$3 );
11758 _computeIntersections( raycaster, intersects, rayLocalSpace ) {
11762 const geometry = this.geometry;
11763 const material = this.material;
11765 const index = geometry.index;
11766 const position = geometry.attributes.position;
11767 const uv = geometry.attributes.uv;
11768 const uv1 = geometry.attributes.uv1;
11769 const normal = geometry.attributes.normal;
11770 const groups = geometry.groups;
11771 const drawRange = geometry.drawRange;
11773 if ( index !==
null ) {
11777 if (
Array.isArray( material ) ) {
11779 for ( let
i = 0, il = groups.length;
i < il;
i ++ ) {
11781 const group = groups[
i ];
11782 const groupMaterial = material[ group.materialIndex ];
11784 const start =
Math.max( group.start, drawRange.start );
11785 const end =
Math.min( index.count,
Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
11787 for ( let
j = start, jl = end;
j < jl;
j += 3 ) {
11789 const a = index.getX(
j );
11790 const b = index.getX(
j + 1 );
11791 const c = index.getX(
j + 2 );
11793 intersection = checkGeometryIntersection(
this, groupMaterial, raycaster, rayLocalSpace, uv, uv1,
normal,
a,
b,
c );
11795 if ( intersection ) {
11797 intersection.faceIndex =
Math.floor(
j / 3 );
11798 intersection.face.materialIndex = group.materialIndex;
11799 intersects.push( intersection );
11809 const start =
Math.max( 0, drawRange.start );
11810 const end =
Math.min( index.count, ( drawRange.start + drawRange.count ) );
11812 for ( let
i = start, il = end;
i < il;
i += 3 ) {
11814 const a = index.getX(
i );
11815 const b = index.getX(
i + 1 );
11816 const c = index.getX(
i + 2 );
11818 intersection = checkGeometryIntersection(
this, material, raycaster, rayLocalSpace, uv, uv1,
normal,
a,
b,
c );
11820 if ( intersection ) {
11822 intersection.faceIndex =
Math.floor(
i / 3 );
11823 intersects.push( intersection );
11835 if (
Array.isArray( material ) ) {
11837 for ( let
i = 0, il = groups.length;
i < il;
i ++ ) {
11839 const group = groups[
i ];
11840 const groupMaterial = material[ group.materialIndex ];
11842 const start =
Math.max( group.start, drawRange.start );
11843 const end =
Math.min(
position.count,
Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) );
11845 for ( let
j = start, jl = end;
j < jl;
j += 3 ) {
11851 intersection = checkGeometryIntersection(
this, groupMaterial, raycaster, rayLocalSpace, uv, uv1,
normal,
a,
b,
c );
11853 if ( intersection ) {
11855 intersection.faceIndex =
Math.floor(
j / 3 );
11856 intersection.face.materialIndex = group.materialIndex;
11857 intersects.push( intersection );
11867 const start =
Math.max( 0, drawRange.start );
11868 const end =
Math.min(
position.count, ( drawRange.start + drawRange.count ) );
11870 for ( let
i = start, il = end;
i < il;
i += 3 ) {
11876 intersection = checkGeometryIntersection(
this, material, raycaster, rayLocalSpace, uv, uv1,
normal,
a,
b,
c );
11878 if ( intersection ) {
11880 intersection.faceIndex =
Math.floor(
i / 3 );
11881 intersects.push( intersection );
11895 function checkIntersection(
object, material, raycaster, ray, pA, pB, pC, point ) {
11899 if ( material.side ===
BackSide ) {
11901 intersect = ray.intersectTriangle( pC, pB, pA,
true, point );
11905 intersect = ray.intersectTriangle( pA, pB, pC, ( material.side ===
FrontSide ), point );
11909 if ( intersect ===
null )
return null;
11911 _intersectionPointWorld.copy( point );
11912 _intersectionPointWorld.applyMatrix4(
object.matrixWorld );
11914 const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld );
11916 if ( distance < raycaster.near || distance > raycaster.far )
return null;
11919 distance: distance,
11920 point: _intersectionPointWorld.clone(),
11926 function checkGeometryIntersection(
object, material, raycaster, ray, uv, uv1,
normal,
a,
b,
c ) {
11928 object.getVertexPosition(
a, _vA$1 );
11929 object.getVertexPosition(
b, _vB$1 );
11930 object.getVertexPosition(
c, _vC$1 );
11932 const intersection = checkIntersection(
object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint );
11934 if ( intersection ) {
11938 _uvA$1.fromBufferAttribute( uv,
a );
11939 _uvB$1.fromBufferAttribute( uv,
b );
11940 _uvC$1.fromBufferAttribute( uv,
c );
11942 intersection.uv =
Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1,
new Vector2() );
11948 _uvA$1.fromBufferAttribute( uv1,
a );
11949 _uvB$1.fromBufferAttribute( uv1,
b );
11950 _uvC$1.fromBufferAttribute( uv1,
c );
11952 intersection.uv1 =
Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1,
new Vector2() );
11953 intersection.uv2 = intersection.uv1;
11959 _normalA.fromBufferAttribute(
normal,
a );
11960 _normalB.fromBufferAttribute(
normal,
b );
11961 _normalC.fromBufferAttribute(
normal,
c );
11963 intersection.normal =
Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC,
new Vector3() );
11965 if ( intersection.normal.dot( ray.direction ) > 0 ) {
11967 intersection.normal.multiplyScalar( - 1 );
11981 Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal );
11983 intersection.face = face;
11987 return intersection;
11993 constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) {
11997 this.type =
'BoxGeometry';
11999 this.parameters = {
12003 widthSegments: widthSegments,
12004 heightSegments: heightSegments,
12005 depthSegments: depthSegments
12008 const scope =
this;
12012 widthSegments =
Math.floor( widthSegments );
12013 heightSegments =
Math.floor( heightSegments );
12014 depthSegments =
Math.floor( depthSegments );
12018 const indices = [];
12019 const vertices = [];
12020 const normals = [];
12025 let numberOfVertices = 0;
12026 let groupStart = 0;
12030 buildPlane(
'z',
'y',
'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 );
12031 buildPlane(
'z',
'y',
'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 );
12032 buildPlane(
'x',
'z',
'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 );
12033 buildPlane(
'x',
'z',
'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 );
12034 buildPlane(
'x',
'y',
'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 );
12035 buildPlane(
'x',
'y',
'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 );
12039 this.setIndex( indices );
12040 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
12041 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
12042 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
12044 function buildPlane(
u,
v,
w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) {
12046 const segmentWidth = width / gridX;
12047 const segmentHeight = height / gridY;
12049 const widthHalf = width / 2;
12050 const heightHalf = height / 2;
12051 const depthHalf = depth / 2;
12053 const gridX1 = gridX + 1;
12054 const gridY1 = gridY + 1;
12056 let vertexCounter = 0;
12057 let groupCount = 0;
12059 const vector =
new Vector3();
12063 for ( let iy = 0; iy < gridY1; iy ++ ) {
12065 const y = iy * segmentHeight - heightHalf;
12067 for ( let ix = 0; ix < gridX1; ix ++ ) {
12069 const x = ix * segmentWidth - widthHalf;
12073 vector[
u ] =
x * udir;
12074 vector[
v ] =
y * vdir;
12075 vector[
w ] = depthHalf;
12079 vertices.push( vector.x, vector.y, vector.z );
12085 vector[
w ] = depth > 0 ? 1 : - 1;
12089 normals.push( vector.x, vector.y, vector.z );
12093 uvs.push( ix / gridX );
12094 uvs.push( 1 - ( iy / gridY ) );
12098 vertexCounter += 1;
12110 for ( let iy = 0; iy < gridY; iy ++ ) {
12112 for ( let ix = 0; ix < gridX; ix ++ ) {
12114 const a = numberOfVertices + ix + gridX1 * iy;
12115 const b = numberOfVertices + ix + gridX1 * ( iy + 1 );
12116 const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 );
12117 const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy;
12121 indices.push(
a,
b,
d );
12122 indices.push(
b,
c,
d );
12134 scope.addGroup( groupStart, groupCount, materialIndex );
12138 groupStart += groupCount;
12142 numberOfVertices += vertexCounter;
12150 super.copy( source );
12152 this.parameters = Object.assign( {}, source.parameters );
12158 static fromJSON( data ) {
12160 return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments );
12170 function cloneUniforms( src ) {
12174 for (
const u in src ) {
12178 for (
const p in src[
u ] ) {
12180 const property = src[
u ][
p ];
12182 if ( property && ( property.isColor ||
12183 property.isMatrix3 || property.isMatrix4 ||
12184 property.isVector2 || property.isVector3 || property.isVector4 ||
12185 property.isTexture || property.isQuaternion ) ) {
12187 if ( property.isRenderTargetTexture ) {
12189 console.warn(
'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' );
12190 dst[
u ][
p ] =
null;
12194 dst[
u ][
p ] =
property.clone();
12198 }
else if (
Array.isArray( property ) ) {
12200 dst[
u ][
p ] =
property.slice();
12204 dst[
u ][
p ] = property;
12216 function mergeUniforms( uniforms ) {
12220 for ( let
u = 0;
u < uniforms.length;
u ++ ) {
12222 const tmp = cloneUniforms( uniforms[
u ] );
12224 for (
const p in tmp ) {
12226 merged[
p ] = tmp[
p ];
12236 function cloneUniformsGroups( src ) {
12240 for ( let
u = 0;
u < src.length;
u ++ ) {
12242 dst.push( src[
u ].
clone() );
12250 function getUnlitUniformColorSpace( renderer ) {
12252 if ( renderer.getRenderTarget() ===
null ) {
12255 return renderer.outputColorSpace;
12259 return ColorManagement.workingColorSpace;
12267 var
default_vertex =
"void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}";
12269 var default_fragment =
"void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}";
12273 constructor( parameters ) {
12277 this.isShaderMaterial =
true;
12279 this.type =
'ShaderMaterial';
12282 this.uniforms = {};
12283 this.uniformsGroups = [];
12286 this.fragmentShader = default_fragment;
12288 this.linewidth = 1;
12290 this.wireframe =
false;
12291 this.wireframeLinewidth = 1;
12294 this.lights =
false;
12295 this.clipping =
false;
12297 this.forceSinglePass =
true;
12299 this.extensions = {
12300 derivatives:
false,
12302 drawBuffers:
false,
12303 shaderTextureLOD:
false,
12304 clipCullDistance:
false
12309 this.defaultAttributeValues = {
12310 'color': [ 1, 1, 1 ],
12316 this.uniformsNeedUpdate =
false;
12318 this.glslVersion =
null;
12322 this.setValues( parameters );
12330 super.copy( source );
12332 this.fragmentShader = source.fragmentShader;
12333 this.vertexShader = source.vertexShader;
12335 this.uniforms = cloneUniforms( source.uniforms );
12336 this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups );
12338 this.defines = Object.assign( {}, source.defines );
12340 this.wireframe = source.wireframe;
12341 this.wireframeLinewidth = source.wireframeLinewidth;
12343 this.fog = source.fog;
12344 this.lights = source.lights;
12345 this.clipping = source.clipping;
12347 this.extensions = Object.assign( {}, source.extensions );
12349 this.glslVersion = source.glslVersion;
12357 const data = super.toJSON( meta );
12359 data.glslVersion = this.glslVersion;
12360 data.uniforms = {};
12362 for (
const name in this.uniforms ) {
12364 const uniform = this.uniforms[ name ];
12365 const value = uniform.value;
12367 if ( value && value.isTexture ) {
12369 data.uniforms[ name ] = {
12371 value: value.toJSON( meta ).uuid
12374 }
else if ( value && value.isColor ) {
12376 data.uniforms[ name ] = {
12378 value: value.getHex()
12381 }
else if ( value && value.isVector2 ) {
12383 data.uniforms[ name ] = {
12385 value: value.toArray()
12388 }
else if ( value && value.isVector3 ) {
12390 data.uniforms[ name ] = {
12392 value: value.toArray()
12395 }
else if ( value && value.isVector4 ) {
12397 data.uniforms[ name ] = {
12399 value: value.toArray()
12402 }
else if ( value && value.isMatrix3 ) {
12404 data.uniforms[ name ] = {
12406 value: value.toArray()
12409 }
else if ( value && value.isMatrix4 ) {
12411 data.uniforms[ name ] = {
12413 value: value.toArray()
12418 data.uniforms[ name ] = {
12428 if ( Object.keys(
this.defines ).length > 0 ) data.defines = this.defines;
12430 data.vertexShader = this.vertexShader;
12431 data.fragmentShader = this.fragmentShader;
12433 data.lights = this.lights;
12434 data.clipping = this.clipping;
12436 const extensions = {};
12438 for (
const key in this.extensions ) {
12440 if ( this.extensions[ key ] ===
true ) extensions[ key ] =
true;
12444 if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions;
12458 this.isCamera =
true;
12460 this.type =
'Camera';
12462 this.matrixWorldInverse =
new Matrix4();
12464 this.projectionMatrix =
new Matrix4();
12465 this.projectionMatrixInverse =
new Matrix4();
12467 this.coordinateSystem = WebGLCoordinateSystem;
12471 copy( source, recursive ) {
12473 super.copy( source, recursive );
12475 this.matrixWorldInverse.copy( source.matrixWorldInverse );
12477 this.projectionMatrix.copy( source.projectionMatrix );
12478 this.projectionMatrixInverse.copy( source.projectionMatrixInverse );
12480 this.coordinateSystem = source.coordinateSystem;
12486 getWorldDirection( target ) {
12488 return super.getWorldDirection( target ).negate();
12494 super.updateMatrixWorld( force );
12496 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
12500 updateWorldMatrix( updateParents, updateChildren ) {
12502 super.updateWorldMatrix( updateParents, updateChildren );
12504 this.matrixWorldInverse.copy( this.matrixWorld ).invert();
12510 return new this.constructor().copy(
this );
12518 constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) {
12522 this.isPerspectiveCamera =
true;
12524 this.type =
'PerspectiveCamera';
12533 this.aspect = aspect;
12536 this.filmGauge = 35;
12537 this.filmOffset = 0;
12543 copy( source, recursive ) {
12545 super.copy( source, recursive );
12547 this.fov = source.fov;
12548 this.zoom = source.zoom;
12550 this.near = source.near;
12551 this.far = source.far;
12552 this.focus = source.focus;
12554 this.aspect = source.aspect;
12555 this.view = source.view ===
null ? null : Object.assign( {}, source.view );
12557 this.filmGauge = source.filmGauge;
12558 this.filmOffset = source.filmOffset;
12572 setFocalLength( focalLength ) {
12575 const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength;
12577 this.fov = RAD2DEG * 2 *
Math.atan( vExtentSlope );
12587 const vExtentSlope =
Math.tan( DEG2RAD * 0.5 * this.fov );
12589 return 0.5 * this.getFilmHeight() / vExtentSlope;
12593 getEffectiveFOV() {
12595 return RAD2DEG * 2 *
Math.atan(
12596 Math.tan( DEG2RAD * 0.5 *
this.fov ) /
this.zoom );
12603 return this.filmGauge *
Math.min( this.aspect, 1 );
12610 return this.filmGauge /
Math.max( this.aspect, 1 );
12651 this.aspect = fullWidth / fullHeight;
12653 if ( this.view ===
null ) {
12667 this.view.enabled =
true;
12668 this.view.fullWidth = fullWidth;
12669 this.view.fullHeight = fullHeight;
12670 this.view.offsetX =
x;
12671 this.view.offsetY =
y;
12672 this.view.width = width;
12673 this.view.height = height;
12679 clearViewOffset() {
12681 if ( this.view !==
null ) {
12683 this.view.enabled =
false;
12693 const near = this.near;
12694 let top = near *
Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom;
12695 let height = 2 * top;
12696 let width = this.aspect * height;
12697 let left = - 0.5 * width;
12698 const view = this.view;
12700 if ( this.view !==
null && this.view.enabled ) {
12702 const fullWidth = view.fullWidth,
12703 fullHeight = view.fullHeight;
12705 left += view.offsetX * width / fullWidth;
12706 top -= view.offsetY * height / fullHeight;
12707 width *= view.width / fullWidth;
12708 height *= view.height / fullHeight;
12712 const skew = this.filmOffset;
12713 if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
12715 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem );
12717 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
12723 const data = super.toJSON( meta );
12725 data.object.fov = this.fov;
12726 data.object.zoom = this.zoom;
12728 data.object.near = this.near;
12729 data.object.far = this.far;
12730 data.object.focus = this.focus;
12732 data.object.aspect = this.aspect;
12734 if ( this.view !==
null ) data.object.view = Object.assign( {}, this.view );
12736 data.object.filmGauge = this.filmGauge;
12737 data.object.filmOffset = this.filmOffset;
12750 constructor( near, far, renderTarget ) {
12754 this.type =
'CubeCamera';
12756 this.renderTarget = renderTarget;
12757 this.coordinateSystem =
null;
12758 this.activeMipmapLevel = 0;
12761 cameraPX.layers = this.layers;
12762 this.
add( cameraPX );
12765 cameraNX.layers = this.layers;
12766 this.
add( cameraNX );
12769 cameraPY.layers = this.layers;
12770 this.
add( cameraPY );
12773 cameraNY.layers = this.layers;
12774 this.
add( cameraNY );
12777 cameraPZ.layers = this.layers;
12778 this.
add( cameraPZ );
12781 cameraNZ.layers = this.layers;
12782 this.
add( cameraNZ );
12786 updateCoordinateSystem() {
12788 const coordinateSystem = this.coordinateSystem;
12790 const cameras = this.children.concat();
12792 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras;
12794 for (
const camera of cameras ) this.
remove( camera );
12796 if ( coordinateSystem === WebGLCoordinateSystem ) {
12798 cameraPX.up.set( 0, 1, 0 );
12799 cameraPX.lookAt( 1, 0, 0 );
12801 cameraNX.up.set( 0, 1, 0 );
12802 cameraNX.lookAt( - 1, 0, 0 );
12804 cameraPY.up.set( 0, 0, - 1 );
12805 cameraPY.lookAt( 0, 1, 0 );
12807 cameraNY.up.set( 0, 0, 1 );
12808 cameraNY.lookAt( 0, - 1, 0 );
12810 cameraPZ.up.set( 0, 1, 0 );
12811 cameraPZ.lookAt( 0, 0, 1 );
12813 cameraNZ.up.set( 0, 1, 0 );
12814 cameraNZ.lookAt( 0, 0, - 1 );
12816 }
else if ( coordinateSystem === WebGPUCoordinateSystem ) {
12818 cameraPX.up.set( 0, - 1, 0 );
12819 cameraPX.lookAt( - 1, 0, 0 );
12821 cameraNX.up.set( 0, - 1, 0 );
12822 cameraNX.lookAt( 1, 0, 0 );
12824 cameraPY.up.set( 0, 0, 1 );
12825 cameraPY.lookAt( 0, 1, 0 );
12827 cameraNY.up.set( 0, 0, - 1 );
12828 cameraNY.lookAt( 0, - 1, 0 );
12830 cameraPZ.up.set( 0, - 1, 0 );
12831 cameraPZ.lookAt( 0, 0, 1 );
12833 cameraNZ.up.set( 0, - 1, 0 );
12834 cameraNZ.lookAt( 0, 0, - 1 );
12838 throw new Error(
'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem );
12842 for (
const camera of cameras ) {
12844 this.
add( camera );
12846 camera.updateMatrixWorld();
12852 update( renderer, scene ) {
12856 const { renderTarget, activeMipmapLevel } =
this;
12858 if ( this.coordinateSystem !== renderer.coordinateSystem ) {
12860 this.coordinateSystem = renderer.coordinateSystem;
12862 this.updateCoordinateSystem();
12866 const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children;
12868 const currentRenderTarget = renderer.getRenderTarget();
12869 const currentActiveCubeFace = renderer.getActiveCubeFace();
12870 const currentActiveMipmapLevel = renderer.getActiveMipmapLevel();
12872 const currentXrEnabled = renderer.xr.enabled;
12874 renderer.xr.enabled =
false;
12876 const generateMipmaps = renderTarget.texture.generateMipmaps;
12878 renderTarget.texture.generateMipmaps =
false;
12880 renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel );
12881 renderer.render( scene, cameraPX );
12883 renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel );
12884 renderer.render( scene, cameraNX );
12886 renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel );
12887 renderer.render( scene, cameraPY );
12889 renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel );
12890 renderer.render( scene, cameraNY );
12892 renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel );
12893 renderer.render( scene, cameraPZ );
12898 renderTarget.texture.generateMipmaps = generateMipmaps;
12900 renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel );
12901 renderer.render( scene, cameraNZ );
12903 renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel );
12905 renderer.xr.enabled = currentXrEnabled;
12907 renderTarget.texture.needsPMREMUpdate =
true;
12915 constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) {
12917 images = images !==
undefined ? images : [];
12920 super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
12922 this.isCubeTexture =
true;
12924 this.flipY =
false;
12934 set images( value ) {
12936 this.image = value;
12944 constructor( size = 1, options = {} ) {
12946 super( size, size, options );
12948 this.isWebGLCubeRenderTarget =
true;
12950 const image = { width: size, height: size, depth: 1 };
12951 const images = [ image, image, image, image, image, image ];
12953 if ( options.encoding !==
undefined ) {
12956 warnOnce(
'THREE.WebGLCubeRenderTarget: option.encoding has been replaced by option.colorSpace.' );
12957 options.colorSpace = options.encoding === sRGBEncoding ? SRGBColorSpace : NoColorSpace;
12961 this.texture =
new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace );
12971 this.texture.isRenderTargetTexture =
true;
12973 this.texture.generateMipmaps = options.generateMipmaps !==
undefined ? options.generateMipmaps :
false;
12978 fromEquirectangularTexture( renderer, texture ) {
12980 this.texture.type = texture.type;
12981 this.texture.colorSpace = texture.colorSpace;
12983 this.texture.generateMipmaps = texture.generateMipmaps;
12984 this.texture.minFilter = texture.minFilter;
12985 this.texture.magFilter = texture.magFilter;
12990 tEquirect: { value:
null },
12995 varying vec3 vWorldDirection;
12997 vec3 transformDirection( in vec3 dir, in mat4 matrix ) {
12999 return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );
13005 vWorldDirection = transformDirection(
position, modelMatrix );
13007 #include <begin_vertex>
13008 #include <project_vertex>
13015 uniform sampler2D tEquirect;
13017 varying vec3 vWorldDirection;
13023 vec3 direction = normalize( vWorldDirection );
13025 vec2 sampleUV = equirectUv( direction );
13027 gl_FragColor = texture2D( tEquirect, sampleUV );
13037 name:
'CubemapFromEquirect',
13039 uniforms: cloneUniforms( shader.uniforms ),
13040 vertexShader: shader.vertexShader,
13041 fragmentShader: shader.fragmentShader,
13047 material.uniforms.tEquirect.value = texture;
13049 const mesh =
new Mesh( geometry, material );
13051 const currentMinFilter = texture.minFilter;
13054 if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter =
LinearFilter;
13056 const camera =
new CubeCamera( 1, 10,
this );
13057 camera.update( renderer, mesh );
13059 texture.minFilter = currentMinFilter;
13061 mesh.geometry.dispose();
13062 mesh.material.dispose();
13068 clear( renderer, color, depth, stencil ) {
13070 const currentRenderTarget = renderer.getRenderTarget();
13072 for ( let
i = 0;
i < 6;
i ++ ) {
13074 renderer.setRenderTarget(
this,
i );
13076 renderer.clear( color, depth, stencil );
13080 renderer.setRenderTarget( currentRenderTarget );
13086 const _vector1 =
new Vector3();
13087 const _vector2 =
new Vector3();
13088 const _normalMatrix =
new Matrix3();
13092 constructor(
normal =
new Vector3( 1, 0, 0 ), constant = 0 ) {
13094 this.isPlane =
true;
13099 this.constant = constant;
13103 set(
normal, constant ) {
13106 this.constant = constant;
13112 setComponents(
x,
y,
z,
w ) {
13121 setFromNormalAndCoplanarPoint(
normal, point ) {
13124 this.constant = - point.dot( this.
normal );
13130 setFromCoplanarPoints(
a,
b,
c ) {
13132 const normal = _vector1.subVectors(
c,
b ).cross( _vector2.subVectors(
a,
b ) ).normalize();
13136 this.setFromNormalAndCoplanarPoint(
normal,
a );
13144 this.
normal.copy( plane.normal );
13145 this.constant = plane.constant;
13155 const inverseNormalLength = 1.0 / this.
normal.length();
13156 this.
normal.multiplyScalar( inverseNormalLength );
13157 this.constant *= inverseNormalLength;
13165 this.constant *= - 1;
13172 distanceToPoint( point ) {
13174 return this.
normal.dot( point ) + this.constant;
13178 distanceToSphere( sphere ) {
13180 return this.distanceToPoint( sphere.center ) - sphere.radius;
13184 projectPoint( point, target ) {
13186 return target.copy( point ).addScaledVector( this.
normal, - this.distanceToPoint( point ) );
13190 intersectLine( line, target ) {
13192 const direction = line.delta( _vector1 );
13194 const denominator = this.
normal.dot( direction );
13196 if ( denominator === 0 ) {
13199 if ( this.distanceToPoint( line.start ) === 0 ) {
13201 return target.copy( line.start );
13210 const t = - ( line.start.dot( this.
normal ) + this.constant ) / denominator;
13218 return target.copy( line.start ).addScaledVector( direction,
t );
13222 intersectsLine( line ) {
13226 const startSign = this.distanceToPoint( line.start );
13227 const endSign = this.distanceToPoint( line.end );
13229 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 );
13233 intersectsBox( box ) {
13235 return box.intersectsPlane(
this );
13239 intersectsSphere( sphere ) {
13241 return sphere.intersectsPlane(
this );
13245 coplanarPoint( target ) {
13247 return target.copy( this.
normal ).multiplyScalar( - this.constant );
13251 applyMatrix4( matrix, optionalNormalMatrix ) {
13253 const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix );
13255 const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix );
13257 const normal = this.
normal.applyMatrix3( normalMatrix ).normalize();
13259 this.constant = - referencePoint.dot(
normal );
13265 translate( offset ) {
13267 this.constant -= offset.dot( this.
normal );
13275 return plane.normal.equals( this.
normal ) && ( plane.constant === this.constant );
13281 return new this.constructor().copy(
this );
13287 const _sphere$5 =
new Sphere();
13288 const _vector$7 =
new Vector3();
13294 this.planes = [ p0, p1, p2, p3, p4, p5 ];
13298 set( p0, p1, p2, p3, p4, p5 ) {
13300 const planes = this.planes;
13302 planes[ 0 ].copy( p0 );
13303 planes[ 1 ].copy( p1 );
13304 planes[ 2 ].copy( p2 );
13305 planes[ 3 ].copy( p3 );
13306 planes[ 4 ].copy( p4 );
13307 planes[ 5 ].copy( p5 );
13315 const planes = this.planes;
13317 for ( let
i = 0;
i < 6;
i ++ ) {
13319 planes[
i ].copy( frustum.planes[
i ] );
13327 setFromProjectionMatrix(
m, coordinateSystem = WebGLCoordinateSystem ) {
13329 const planes = this.planes;
13330 const me =
m.elements;
13331 const me0 =
me[ 0 ], me1 =
me[ 1 ], me2 =
me[ 2 ], me3 =
me[ 3 ];
13332 const me4 =
me[ 4 ], me5 =
me[ 5 ], me6 =
me[ 6 ], me7 =
me[ 7 ];
13333 const me8 =
me[ 8 ], me9 =
me[ 9 ], me10 =
me[ 10 ], me11 =
me[ 11 ];
13334 const me12 =
me[ 12 ], me13 =
me[ 13 ], me14 =
me[ 14 ], me15 =
me[ 15 ];
13336 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
13337 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
13338 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
13339 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
13340 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
13342 if ( coordinateSystem === WebGLCoordinateSystem ) {
13344 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
13346 }
else if ( coordinateSystem === WebGPUCoordinateSystem ) {
13348 planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize();
13352 throw new Error(
'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem );
13360 intersectsObject(
object ) {
13362 if (
object.boundingSphere !==
undefined ) {
13364 if (
object.boundingSphere ===
null )
object.computeBoundingSphere();
13366 _sphere$5.copy(
object.boundingSphere ).applyMatrix4(
object.matrixWorld );
13370 const geometry =
object.geometry;
13372 if ( geometry.boundingSphere ===
null ) geometry.computeBoundingSphere();
13374 _sphere$5.copy( geometry.boundingSphere ).applyMatrix4(
object.matrixWorld );
13378 return this.intersectsSphere( _sphere$5 );
13382 intersectsSprite( sprite ) {
13384 _sphere$5.center.set( 0, 0, 0 );
13385 _sphere$5.radius = 0.7071067811865476;
13386 _sphere$5.applyMatrix4( sprite.matrixWorld );
13388 return this.intersectsSphere( _sphere$5 );
13392 intersectsSphere( sphere ) {
13394 const planes = this.planes;
13395 const center = sphere.center;
13396 const negRadius = - sphere.radius;
13398 for ( let
i = 0;
i < 6;
i ++ ) {
13400 const distance = planes[
i ].distanceToPoint( center );
13402 if ( distance < negRadius ) {
13414 intersectsBox( box ) {
13416 const planes = this.planes;
13418 for ( let
i = 0;
i < 6;
i ++ ) {
13420 const plane = planes[
i ];
13424 _vector$7.x = plane.normal.x > 0 ? box.max.x : box.min.x;
13425 _vector$7.y = plane.normal.y > 0 ? box.max.y : box.min.y;
13426 _vector$7.z = plane.normal.z > 0 ? box.max.z : box.min.z;
13428 if ( plane.distanceToPoint( _vector$7 ) < 0 ) {
13442 const planes = this.planes;
13444 for ( let
i = 0;
i < 6;
i ++ ) {
13446 if ( planes[
i ].distanceToPoint( point ) < 0 ) {
13460 return new this.constructor().copy(
this );
13466 function WebGLAnimation() {
13468 let context =
null;
13469 let isAnimating =
false;
13470 let animationLoop =
null;
13471 let requestId =
null;
13473 function onAnimationFrame( time, frame ) {
13475 animationLoop( time, frame );
13477 requestId = context.requestAnimationFrame( onAnimationFrame );
13483 start:
function () {
13485 if ( isAnimating ===
true )
return;
13486 if ( animationLoop ===
null )
return;
13488 requestId = context.requestAnimationFrame( onAnimationFrame );
13490 isAnimating =
true;
13494 stop:
function () {
13496 context.cancelAnimationFrame( requestId );
13498 isAnimating =
false;
13502 setAnimationLoop:
function ( callback ) {
13504 animationLoop = callback;
13508 setContext:
function ( value ) {
13518 function WebGLAttributes( gl, capabilities ) {
13520 const isWebGL2 = capabilities.isWebGL2;
13522 const buffers =
new WeakMap();
13524 function createBuffer( attribute, bufferType ) {
13526 const array = attribute.array;
13527 const usage = attribute.usage;
13528 const size = array.byteLength;
13530 const buffer = gl.createBuffer();
13532 gl.bindBuffer( bufferType, buffer );
13533 gl.bufferData( bufferType, array, usage );
13535 attribute.onUploadCallback();
13545 if ( attribute.isFloat16BufferAttribute ) {
13549 type = gl.HALF_FLOAT;
13553 throw new Error(
'THREE.WebGLAttributes: Usage of Float16BufferAttribute requires WebGL2.' );
13559 type = gl.UNSIGNED_SHORT;
13569 type = gl.UNSIGNED_INT;
13575 }
else if ( array instanceof
Int8Array ) {
13581 type = gl.UNSIGNED_BYTE;
13585 type = gl.UNSIGNED_BYTE;
13589 throw new Error(
'THREE.WebGLAttributes: Unsupported buffer data format: ' + array );
13596 bytesPerElement: array.BYTES_PER_ELEMENT,
13603 function updateBuffer( buffer, attribute, bufferType ) {
13605 const array = attribute.array;
13606 const updateRange = attribute._updateRange;
13607 const updateRanges = attribute.updateRanges;
13609 gl.bindBuffer( bufferType, buffer );
13611 if ( updateRange.count === - 1 && updateRanges.length === 0 ) {
13614 gl.bufferSubData( bufferType, 0, array );
13618 if ( updateRanges.length !== 0 ) {
13620 for ( let
i = 0,
l = updateRanges.length;
i <
l;
i ++ ) {
13622 const range = updateRanges[
i ];
13625 gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
13626 array, range.start, range.count );
13630 gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT,
13631 array.subarray( range.start, range.start + range.count ) );
13637 attribute.clearUpdateRanges();
13642 if ( updateRange.count !== - 1 ) {
13646 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
13647 array, updateRange.offset, updateRange.count );
13651 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
13652 array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
13656 updateRange.count = - 1;
13660 attribute.onUploadCallback();
13666 function get( attribute ) {
13668 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13670 return buffers.get( attribute );
13674 function remove( attribute ) {
13676 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13678 const data = buffers.get( attribute );
13682 gl.deleteBuffer( data.buffer );
13684 buffers.delete( attribute );
13690 function update( attribute, bufferType ) {
13692 if ( attribute.isGLBufferAttribute ) {
13694 const cached = buffers.get( attribute );
13696 if ( ! cached || cached.version < attribute.version ) {
13698 buffers.set( attribute, {
13699 buffer: attribute.buffer,
13700 type: attribute.type,
13701 bytesPerElement: attribute.elementSize,
13711 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
13713 const data = buffers.get( attribute );
13717 buffers.set( attribute, createBuffer( attribute, bufferType ) );
13719 }
else if ( data.version < attribute.version ) {
13721 if ( data.size !== attribute.array.byteLength ) {
13723 throw new Error(
'THREE.WebGLAttributes: The size of the buffer attribute\'s array buffer does not match the original size. Resizing buffer attributes is not supported.' );
13727 updateBuffer( data.buffer, attribute, bufferType );
13729 data.version = attribute.version;
13747 constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) {
13751 this.type =
'PlaneGeometry';
13753 this.parameters = {
13756 widthSegments: widthSegments,
13757 heightSegments: heightSegments
13760 const width_half = width / 2;
13761 const height_half = height / 2;
13763 const gridX =
Math.floor( widthSegments );
13764 const gridY =
Math.floor( heightSegments );
13766 const gridX1 = gridX + 1;
13767 const gridY1 = gridY + 1;
13769 const segment_width = width / gridX;
13770 const segment_height = height / gridY;
13774 const indices = [];
13775 const vertices = [];
13776 const normals = [];
13779 for ( let iy = 0; iy < gridY1; iy ++ ) {
13781 const y = iy * segment_height - height_half;
13783 for ( let ix = 0; ix < gridX1; ix ++ ) {
13785 const x = ix * segment_width - width_half;
13787 vertices.push(
x, -
y, 0 );
13789 normals.push( 0, 0, 1 );
13791 uvs.push( ix / gridX );
13792 uvs.push( 1 - ( iy / gridY ) );
13798 for ( let iy = 0; iy < gridY; iy ++ ) {
13800 for ( let ix = 0; ix < gridX; ix ++ ) {
13802 const a = ix + gridX1 * iy;
13803 const b = ix + gridX1 * ( iy + 1 );
13804 const c = ( ix + 1 ) + gridX1 * ( iy + 1 );
13805 const d = ( ix + 1 ) + gridX1 * iy;
13807 indices.push(
a,
b,
d );
13808 indices.push(
b,
c,
d );
13814 this.setIndex( indices );
13815 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
13816 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
13817 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
13823 super.copy( source );
13825 this.parameters = Object.assign( {}, source.parameters );
13831 static fromJSON( data ) {
13833 return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments );
13839 var alphahash_fragment =
"#ifdef USE_ALPHAHASH\n\tif ( diffuseColor.a < getAlphaHashThreshold( vPosition ) ) discard;\n#endif";
13841 var alphahash_pars_fragment =
"#ifdef USE_ALPHAHASH\n\tconst float ALPHA_HASH_SCALE = 0.05;\n\tfloat hash2D( vec2 value ) {\n\t\treturn fract( 1.0e4 * sin( 17.0 * value.x + 0.1 * value.y ) * ( 0.1 + abs( sin( 13.0 * value.y + value.x ) ) ) );\n\t}\n\tfloat hash3D( vec3 value ) {\n\t\treturn hash2D( vec2( hash2D( value.xy ), value.z ) );\n\t}\n\tfloat getAlphaHashThreshold( vec3 position ) {\n\t\tfloat maxDeriv = max(\n\t\t\tlength( dFdx( position.xyz ) ),\n\t\t\tlength( dFdy( position.xyz ) )\n\t\t);\n\t\tfloat pixScale = 1.0 / ( ALPHA_HASH_SCALE * maxDeriv );\n\t\tvec2 pixScales = vec2(\n\t\t\texp2( floor( log2( pixScale ) ) ),\n\t\t\texp2( ceil( log2( pixScale ) ) )\n\t\t);\n\t\tvec2 alpha = vec2(\n\t\t\thash3D( floor( pixScales.x * position.xyz ) ),\n\t\t\thash3D( floor( pixScales.y * position.xyz ) )\n\t\t);\n\t\tfloat lerpFactor = fract( log2( pixScale ) );\n\t\tfloat x = ( 1.0 - lerpFactor ) * alpha.x + lerpFactor * alpha.y;\n\t\tfloat a = min( lerpFactor, 1.0 - lerpFactor );\n\t\tvec3 cases = vec3(\n\t\t\tx * x / ( 2.0 * a * ( 1.0 - a ) ),\n\t\t\t( x - 0.5 * a ) / ( 1.0 - a ),\n\t\t\t1.0 - ( ( 1.0 - x ) * ( 1.0 - x ) / ( 2.0 * a * ( 1.0 - a ) ) )\n\t\t);\n\t\tfloat threshold = ( x < ( 1.0 - a ) )\n\t\t\t? ( ( x < a ) ? cases.x : cases.y )\n\t\t\t: cases.z;\n\t\treturn clamp( threshold , 1.0e-6, 1.0 );\n\t}\n#endif";
13843 var
alphamap_fragment =
"#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vAlphaMapUv ).g;\n#endif";
13847 var
alphatest_fragment =
"#ifdef USE_ALPHATEST\n\tif ( diffuseColor.a < alphaTest ) discard;\n#endif";
13849 var alphatest_pars_fragment =
"#ifdef USE_ALPHATEST\n\tuniform float alphaTest;\n#endif";
13851 var aomap_fragment =
"#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vAoMapUv ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_CLEARCOAT ) \n\t\tclearcoatSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_SHEEN ) \n\t\tsheenSpecularIndirect *= ambientOcclusion;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD )\n\t\tfloat dotNV = saturate( dot( geometryNormal, geometryViewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.roughness );\n\t#endif\n#endif";
13853 var aomap_pars_fragment =
"#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif";
13855 var batching_pars_vertex =
"#ifdef USE_BATCHING\n\tattribute float batchId;\n\tuniform highp sampler2D batchingTexture;\n\tmat4 getBatchingMatrix( const in float i ) {\n\t\tint size = textureSize( batchingTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( batchingTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( batchingTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( batchingTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( batchingTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif";
13857 var batching_vertex =
"#ifdef USE_BATCHING\n\tmat4 batchingMatrix = getBatchingMatrix( batchId );\n#endif";
13859 var begin_vertex =
"vec3 transformed = vec3( position );\n#ifdef USE_ALPHAHASH\n\tvPosition = vec3( position );\n#endif";
13861 var beginnormal_vertex =
"vec3 objectNormal = vec3( normal );\n#ifdef USE_TANGENT\n\tvec3 objectTangent = vec3( tangent.xyz );\n#endif";
13863 var bsdfs =
"float G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_BlinnPhong( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, 1.0, dotVH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n} // validated";
13865 var iridescence_fragment =
"#ifdef USE_IRIDESCENCE\n\tconst mat3 XYZ_TO_REC709 = mat3(\n\t\t 3.2404542, -0.9692660, 0.0556434,\n\t\t-1.5371385, 1.8760108, -0.2040259,\n\t\t-0.4985314, 0.0415560, 1.0572252\n\t);\n\tvec3 Fresnel0ToIor( vec3 fresnel0 ) {\n\t\tvec3 sqrtF0 = sqrt( fresnel0 );\n\t\treturn ( vec3( 1.0 ) + sqrtF0 ) / ( vec3( 1.0 ) - sqrtF0 );\n\t}\n\tvec3 IorToFresnel0( vec3 transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - vec3( incidentIor ) ) / ( transmittedIor + vec3( incidentIor ) ) );\n\t}\n\tfloat IorToFresnel0( float transmittedIor, float incidentIor ) {\n\t\treturn pow2( ( transmittedIor - incidentIor ) / ( transmittedIor + incidentIor ));\n\t}\n\tvec3 evalSensitivity( float OPD, vec3 shift ) {\n\t\tfloat phase = 2.0 * PI * OPD * 1.0e-9;\n\t\tvec3 val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 );\n\t\tvec3 pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 );\n\t\tvec3 var = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 );\n\t\tvec3 xyz = val * sqrt( 2.0 * PI * var ) * cos( pos * phase + shift ) * exp( - pow2( phase ) * var );\n\t\txyz.x += 9.7470e-14 * sqrt( 2.0 * PI * 4.5282e+09 ) * cos( 2.2399e+06 * phase + shift[ 0 ] ) * exp( - 4.5282e+09 * pow2( phase ) );\n\t\txyz /= 1.0685e-7;\n\t\tvec3 rgb = XYZ_TO_REC709 * xyz;\n\t\treturn rgb;\n\t}\n\tvec3 evalIridescence( float outsideIOR, float eta2, float cosTheta1, float thinFilmThickness, vec3 baseF0 ) {\n\t\tvec3 I;\n\t\tfloat iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) );\n\t\tfloat sinTheta2Sq = pow2( outsideIOR / iridescenceIOR ) * ( 1.0 - pow2( cosTheta1 ) );\n\t\tfloat cosTheta2Sq = 1.0 - sinTheta2Sq;\n\t\tif ( cosTheta2Sq < 0.0 ) {\n\t\t\treturn vec3( 1.0 );\n\t\t}\n\t\tfloat cosTheta2 = sqrt( cosTheta2Sq );\n\t\tfloat R0 = IorToFresnel0( iridescenceIOR, outsideIOR );\n\t\tfloat R12 = F_Schlick( R0, 1.0, cosTheta1 );\n\t\tfloat T121 = 1.0 - R12;\n\t\tfloat phi12 = 0.0;\n\t\tif ( iridescenceIOR < outsideIOR ) phi12 = PI;\n\t\tfloat phi21 = PI - phi12;\n\t\tvec3 baseIOR = Fresnel0ToIor( clamp( baseF0, 0.0, 0.9999 ) );\t\tvec3 R1 = IorToFresnel0( baseIOR, iridescenceIOR );\n\t\tvec3 R23 = F_Schlick( R1, 1.0, cosTheta2 );\n\t\tvec3 phi23 = vec3( 0.0 );\n\t\tif ( baseIOR[ 0 ] < iridescenceIOR ) phi23[ 0 ] = PI;\n\t\tif ( baseIOR[ 1 ] < iridescenceIOR ) phi23[ 1 ] = PI;\n\t\tif ( baseIOR[ 2 ] < iridescenceIOR ) phi23[ 2 ] = PI;\n\t\tfloat OPD = 2.0 * iridescenceIOR * thinFilmThickness * cosTheta2;\n\t\tvec3 phi = vec3( phi21 ) + phi23;\n\t\tvec3 R123 = clamp( R12 * R23, 1e-5, 0.9999 );\n\t\tvec3 r123 = sqrt( R123 );\n\t\tvec3 Rs = pow2( T121 ) * R23 / ( vec3( 1.0 ) - R123 );\n\t\tvec3 C0 = R12 + Rs;\n\t\tI = C0;\n\t\tvec3 Cm = Rs - T121;\n\t\tfor ( int m = 1; m <= 2; ++ m ) {\n\t\t\tCm *= r123;\n\t\t\tvec3 Sm = 2.0 * evalSensitivity( float( m ) * OPD, float( m ) * phi );\n\t\t\tI += Cm * Sm;\n\t\t}\n\t\treturn max( I, vec3( 0.0 ) );\n\t}\n#endif";
13867 var
bumpmap_pars_fragment =
"#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vBumpMapUv );\n\t\tvec2 dSTdy = dFdy( vBumpMapUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vBumpMapUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vBumpMapUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, float faceDirection ) {\n\t\tvec3 vSigmaX = normalize( dFdx( surf_pos.xyz ) );\n\t\tvec3 vSigmaY = normalize( dFdy( surf_pos.xyz ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 ) * faceDirection;\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif";
13869 var clipping_planes_fragment =
"#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#pragma unroll_loop_end\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\tif ( clipped ) discard;\n\t#endif\n#endif";
13871 var clipping_planes_pars_fragment =
"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif";
13873 var clipping_planes_pars_vertex =
"#if NUM_CLIPPING_PLANES > 0\n\tvarying vec3 vClipPosition;\n#endif";
13875 var clipping_planes_vertex =
"#if NUM_CLIPPING_PLANES > 0\n\tvClipPosition = - mvPosition.xyz;\n#endif";
13877 var
color_fragment =
"#if defined( USE_COLOR_ALPHA )\n\tdiffuseColor *= vColor;\n#elif defined( USE_COLOR )\n\tdiffuseColor.rgb *= vColor;\n#endif";
13879 var
color_pars_fragment =
"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR )\n\tvarying vec3 vColor;\n#endif";
13881 var
color_pars_vertex =
"#if defined( USE_COLOR_ALPHA )\n\tvarying vec4 vColor;\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvarying vec3 vColor;\n#endif";
13883 var
color_vertex =
"#if defined( USE_COLOR_ALPHA )\n\tvColor = vec4( 1.0 );\n#elif defined( USE_COLOR ) || defined( USE_INSTANCING_COLOR )\n\tvColor = vec3( 1.0 );\n#endif\n#ifdef USE_COLOR\n\tvColor *= color;\n#endif\n#ifdef USE_INSTANCING_COLOR\n\tvColor.xyz *= instanceColor.xyz;\n#endif";
13885 var common =
"#define PI 3.141592653589793\n#define PI2 6.283185307179586\n#define PI_HALF 1.5707963267948966\n#define RECIPROCAL_PI 0.3183098861837907\n#define RECIPROCAL_PI2 0.15915494309189535\n#define EPSILON 1e-6\n#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\n#define whiteComplement( a ) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nvec3 pow2( const in vec3 x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat max3( const in vec3 v ) { return max( max( v.x, v.y ), v.z ); }\nfloat average( const in vec3 v ) { return dot( v, vec3( 0.3333333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract( sin( sn ) * c );\n}\n#ifdef HIGH_PRECISION\n\tfloat precisionSafeLength( vec3 v ) { return length( v ); }\n#else\n\tfloat precisionSafeLength( vec3 v ) {\n\t\tfloat maxComponent = max3( abs( v ) );\n\t\treturn length( v / maxComponent ) * maxComponent;\n\t}\n#endif\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat luminance( const in vec3 rgb ) {\n\tconst vec3 weights = vec3( 0.2126729, 0.7151522, 0.0721750 );\n\treturn dot( weights, rgb );\n}\nbool isPerspectiveMatrix( mat4 m ) {\n\treturn m[ 2 ][ 3 ] == - 1.0;\n}\nvec2 equirectUv( in vec3 dir ) {\n\tfloat u = atan( dir.z, dir.x ) * RECIPROCAL_PI2 + 0.5;\n\tfloat v = asin( clamp( dir.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\treturn vec2( u, v );\n}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated";
13887 var cube_uv_reflection_fragment =
"#ifdef ENVMAP_TYPE_CUBE_UV\n\t#define cubeUV_minMipLevel 4.0\n\t#define cubeUV_minTileSize 16.0\n\tfloat getFace( vec3 direction ) {\n\t\tvec3 absDirection = abs( direction );\n\t\tfloat face = - 1.0;\n\t\tif ( absDirection.x > absDirection.z ) {\n\t\t\tif ( absDirection.x > absDirection.y )\n\t\t\t\tface = direction.x > 0.0 ? 0.0 : 3.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t} else {\n\t\t\tif ( absDirection.z > absDirection.y )\n\t\t\t\tface = direction.z > 0.0 ? 2.0 : 5.0;\n\t\t\telse\n\t\t\t\tface = direction.y > 0.0 ? 1.0 : 4.0;\n\t\t}\n\t\treturn face;\n\t}\n\tvec2 getUV( vec3 direction, float face ) {\n\t\tvec2 uv;\n\t\tif ( face == 0.0 ) {\n\t\t\tuv = vec2( direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 1.0 ) {\n\t\t\tuv = vec2( - direction.x, - direction.z ) / abs( direction.y );\n\t\t} else if ( face == 2.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.y ) / abs( direction.z );\n\t\t} else if ( face == 3.0 ) {\n\t\t\tuv = vec2( - direction.z, direction.y ) / abs( direction.x );\n\t\t} else if ( face == 4.0 ) {\n\t\t\tuv = vec2( - direction.x, direction.z ) / abs( direction.y );\n\t\t} else {\n\t\t\tuv = vec2( direction.x, direction.y ) / abs( direction.z );\n\t\t}\n\t\treturn 0.5 * ( uv + 1.0 );\n\t}\n\tvec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {\n\t\tfloat face = getFace( direction );\n\t\tfloat filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );\n\t\tmipInt = max( mipInt, cubeUV_minMipLevel );\n\t\tfloat faceSize = exp2( mipInt );\n\t\thighp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0;\n\t\tif ( face > 2.0 ) {\n\t\t\tuv.y += faceSize;\n\t\t\tface -= 3.0;\n\t\t}\n\t\tuv.x += face * faceSize;\n\t\tuv.x += filterInt * 3.0 * cubeUV_minTileSize;\n\t\tuv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );\n\t\tuv.x *= CUBEUV_TEXEL_WIDTH;\n\t\tuv.y *= CUBEUV_TEXEL_HEIGHT;\n\t\t#ifdef texture2DGradEXT\n\t\t\treturn texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb;\n\t\t#else\n\t\t\treturn texture2D( envMap, uv ).rgb;\n\t\t#endif\n\t}\n\t#define cubeUV_r0 1.0\n\t#define cubeUV_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\n\t#define cubeUV_m6 4.0\n\tfloat roughnessToMip( float roughness ) {\n\t\tfloat mip = 0.0;\n\t\tif ( roughness >= cubeUV_r1 ) {\n\t\t\tmip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;\n\t\t} else if ( roughness >= cubeUV_r4 ) {\n\t\t\tmip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;\n\t\t} else if ( roughness >= cubeUV_r5 ) {\n\t\t\tmip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;\n\t\t} else if ( roughness >= cubeUV_r6 ) {\n\t\t\tmip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;\n\t\t} else {\n\t\t\tmip = - 2.0 * log2( 1.16 * roughness );\t\t}\n\t\treturn mip;\n\t}\n\tvec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {\n\t\tfloat mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );\n\t\tfloat mipF = fract( mip );\n\t\tfloat mipInt = floor( mip );\n\t\tvec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );\n\t\tif ( mipF == 0.0 ) {\n\t\t\treturn vec4( color0, 1.0 );\n\t\t} else {\n\t\t\tvec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );\n\t\t\treturn vec4( mix( color0, color1, mipF ), 1.0 );\n\t\t}\n\t}\n#endif";
13889 var
defaultnormal_vertex =
"vec3 transformedNormal = objectNormal;\n#ifdef USE_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 0.0 ) ).xyz;\n\t#ifdef FLIP_SIDED\n\t\ttransformedTangent = - transformedTangent;\n\t#endif\n#endif";
13891 var displacementmap_pars_vertex =
"#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif";
13893 var displacementmap_vertex =
"#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif";
13895 var emissivemap_fragment =
"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif";
13897 var emissivemap_pars_fragment =
"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif";
13899 var colorspace_fragment =
"gl_FragColor = linearToOutputTexel( gl_FragColor );";
13901 var colorspace_pars_fragment =
"\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.a );\n}\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn sRGBTransferOETF( value );\n}";
13903 var
envmap_fragment =
"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvec3 cameraToFrag;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToFrag = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToFrag = normalize( vWorldPosition - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToFrag, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToFrag, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif";
13905 var envmap_common_pars_fragment =
"#ifdef USE_ENVMAP\n\tuniform float envMapIntensity;\n\tuniform float flipEnvMap;\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\t\n#endif";
13907 var
envmap_pars_fragment =
"#ifdef USE_ENVMAP\n\tuniform float reflectivity;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\tvarying vec3 vWorldPosition;\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif";
13909 var
envmap_pars_vertex =
"#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( LAMBERT )\n\t\t#define ENV_WORLDPOS\n\t#endif\n\t#ifdef ENV_WORLDPOS\n\t\t\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif";
13911 var
envmap_vertex =
"#ifdef USE_ENVMAP\n\t#ifdef ENV_WORLDPOS\n\t\tvWorldPosition = worldPosition.xyz;\n\t#else\n\t\tvec3 cameraToVertex;\n\t\tif ( isOrthographic ) {\n\t\t\tcameraToVertex = normalize( vec3( - viewMatrix[ 0 ][ 2 ], - viewMatrix[ 1 ][ 2 ], - viewMatrix[ 2 ][ 2 ] ) );\n\t\t} else {\n\t\t\tcameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\t}\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif";
13913 var fog_vertex =
"#ifdef USE_FOG\n\tvFogDepth = - mvPosition.z;\n#endif";
13915 var fog_pars_vertex =
"#ifdef USE_FOG\n\tvarying float vFogDepth;\n#endif";
13917 var
fog_fragment =
"#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = 1.0 - exp( - fogDensity * fogDensity * vFogDepth * vFogDepth );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, vFogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif";
13919 var
fog_pars_fragment =
"#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float vFogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif";
13921 var gradientmap_pars_fragment =
"#ifdef USE_GRADIENTMAP\n\tuniform sampler2D gradientMap;\n#endif\nvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\tfloat dotNL = dot( normal, lightDirection );\n\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t#ifdef USE_GRADIENTMAP\n\t\treturn vec3( texture2D( gradientMap, coord ).r );\n\t#else\n\t\tvec2 fw = fwidth( coord ) * 0.5;\n\t\treturn mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( 0.7 - fw.x, 0.7 + fw.x, coord.x ) );\n\t#endif\n}";
13923 var
lightmap_fragment =
"#ifdef USE_LIGHTMAP\n\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\treflectedLight.indirectDiffuse += lightMapIrradiance;\n#endif";
13925 var
lightmap_pars_fragment =
"#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif";
13927 var lights_lambert_fragment =
"LambertMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularStrength = specularStrength;";
13929 var lights_lambert_pars_fragment =
"varying vec3 vViewPosition;\nstruct LambertMaterial {\n\tvec3 diffuseColor;\n\tfloat specularStrength;\n};\nvoid RE_Direct_Lambert( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Lambert( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Lambert\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Lambert";
13931 var lights_pars_begin =
"uniform bool receiveShadow;\nuniform vec3 ambientLightColor;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\nvec3 shGetIrradianceAt( in vec3 normal, in vec3 shCoefficients[ 9 ] ) {\n\tfloat x = normal.x, y = normal.y, z = normal.z;\n\tvec3 result = shCoefficients[ 0 ] * 0.886227;\n\tresult += shCoefficients[ 1 ] * 2.0 * 0.511664 * y;\n\tresult += shCoefficients[ 2 ] * 2.0 * 0.511664 * z;\n\tresult += shCoefficients[ 3 ] * 2.0 * 0.511664 * x;\n\tresult += shCoefficients[ 4 ] * 2.0 * 0.429043 * x * y;\n\tresult += shCoefficients[ 5 ] * 2.0 * 0.429043 * y * z;\n\tresult += shCoefficients[ 6 ] * ( 0.743125 * z * z - 0.247708 );\n\tresult += shCoefficients[ 7 ] * 2.0 * 0.429043 * x * z;\n\tresult += shCoefficients[ 8 ] * 0.429043 * ( x * x - y * y );\n\treturn result;\n}\nvec3 getLightProbeIrradiance( const in vec3 lightProbe[ 9 ], const in vec3 normal ) {\n\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\tvec3 irradiance = shGetIrradianceAt( worldNormal, lightProbe );\n\treturn irradiance;\n}\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\treturn irradiance;\n}\nfloat getDistanceAttenuation( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\t#if defined ( LEGACY_LIGHTS )\n\t\tif ( cutoffDistance > 0.0 && decayExponent > 0.0 ) {\n\t\t\treturn pow( saturate( - lightDistance / cutoffDistance + 1.0 ), decayExponent );\n\t\t}\n\t\treturn 1.0;\n\t#else\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tif ( cutoffDistance > 0.0 ) {\n\t\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\t}\n\t\treturn distanceFalloff;\n\t#endif\n}\nfloat getSpotAttenuation( const in float coneCosine, const in float penumbraCosine, const in float angleCosine ) {\n\treturn smoothstep( coneCosine, penumbraCosine, angleCosine );\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalLightInfo( const in DirectionalLight directionalLight, out IncidentLight light ) {\n\t\tlight.color = directionalLight.color;\n\t\tlight.direction = directionalLight.direction;\n\t\tlight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointLightInfo( const in PointLight pointLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tlight.color = pointLight.color;\n\t\tlight.color *= getDistanceAttenuation( lightDistance, pointLight.distance, pointLight.decay );\n\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotLightInfo( const in SpotLight spotLight, const in vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\n\t\tlight.direction = normalize( lVector );\n\t\tfloat angleCos = dot( light.direction, spotLight.direction );\n\t\tfloat spotAttenuation = getSpotAttenuation( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\tif ( spotAttenuation > 0.0 ) {\n\t\t\tfloat lightDistance = length( lVector );\n\t\t\tlight.color = spotLight.color * spotAttenuation;\n\t\t\tlight.color *= getDistanceAttenuation( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tlight.visible = ( light.color != vec3( 0.0 ) );\n\t\t} else {\n\t\t\tlight.color = vec3( 0.0 );\n\t\t\tlight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in vec3 normal ) {\n\t\tfloat dotNL = dot( normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\treturn irradiance;\n\t}\n#endif";
13933 var envmap_physical_pars_fragment =
"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, worldNormal, 1.0 );\n\t\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\tvec3 getIBLRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 reflectVec = reflect( - viewDir, normal );\n\t\t\treflectVec = normalize( mix( reflectVec, normal, roughness * roughness) );\n\t\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, reflectVec, roughness );\n\t\t\treturn envMapColor.rgb * envMapIntensity;\n\t\t#else\n\t\t\treturn vec3( 0.0 );\n\t\t#endif\n\t}\n\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\n#endif";
13935 var lights_toon_fragment =
"ToonMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;";
13937 var lights_toon_pars_fragment =
"varying vec3 vViewPosition;\nstruct ToonMaterial {\n\tvec3 diffuseColor;\n};\nvoid RE_Direct_Toon( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_Toon\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Toon";
13939 var
lights_phong_fragment =
"BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;";
13941 var
lights_phong_pars_fragment =
"varying vec3 vViewPosition;\nstruct BlinnPhongMaterial {\n\tvec3 diffuseColor;\n\tvec3 specularColor;\n\tfloat specularShininess;\n\tfloat specularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong";
13943 var lights_physical_fragment =
"PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nvec3 dxy = max( abs( dFdx( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\nfloat geometryRoughness = max( max( dxy.x, dxy.y ), dxy.z );\nmaterial.roughness = max( roughnessFactor, 0.0525 );material.roughness += geometryRoughness;\nmaterial.roughness = min( material.roughness, 1.0 );\n#ifdef IOR\n\tmaterial.ior = ior;\n\t#ifdef USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\n\t\t#endif\n\t\tmaterial.specularF90 = mix( specularIntensityFactor, 1.0, metalnessFactor );\n\t#else\n\t\tfloat specularIntensityFactor = 1.0;\n\t\tvec3 specularColorFactor = vec3( 1.0 );\n\t\tmaterial.specularF90 = 1.0;\n\t#endif\n\tmaterial.specularColor = mix( min( pow2( ( material.ior - 1.0 ) / ( material.ior + 1.0 ) ) * specularColorFactor, vec3( 1.0 ) ) * specularIntensityFactor, diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( 0.04 ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.specularF90 = 1.0;\n#endif\n#ifdef USE_CLEARCOAT\n\tmaterial.clearcoat = clearcoat;\n\tmaterial.clearcoatRoughness = clearcoatRoughness;\n\tmaterial.clearcoatF0 = vec3( 0.04 );\n\tmaterial.clearcoatF90 = 1.0;\n\t#ifdef USE_CLEARCOATMAP\n\t\tmaterial.clearcoat *= texture2D( clearcoatMap, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).y;\n\t#endif\n\tmaterial.clearcoat = saturate( material.clearcoat );\tmaterial.clearcoatRoughness = max( material.clearcoatRoughness, 0.0525 );\n\tmaterial.clearcoatRoughness += geometryRoughness;\n\tmaterial.clearcoatRoughness = min( material.clearcoatRoughness, 1.0 );\n#endif\n#ifdef USE_IRIDESCENCE\n\tmaterial.iridescence = iridescence;\n\tmaterial.iridescenceIOR = iridescenceIOR;\n\t#ifdef USE_IRIDESCENCEMAP\n\t\tmaterial.iridescence *= texture2D( iridescenceMap, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).g + iridescenceThicknessMinimum;\n\t#else\n\t\tmaterial.iridescenceThickness = iridescenceThicknessMaximum;\n\t#endif\n#endif\n#ifdef USE_SHEEN\n\tmaterial.sheenColor = sheenColor;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif";
13945 var lights_physical_pars_fragment =
"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat clearcoat;\n\t\tfloat clearcoatRoughness;\n\t\tvec3 clearcoatF0;\n\t\tfloat clearcoatF90;\n\t#endif\n\t#ifdef USE_IRIDESCENCE\n\t\tfloat iridescence;\n\t\tfloat iridescenceIOR;\n\t\tfloat iridescenceThickness;\n\t\tvec3 iridescenceFresnel;\n\t\tvec3 iridescenceF0;\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tvec3 sheenColor;\n\t\tfloat sheenRoughness;\n\t#endif\n\t#ifdef IOR\n\t\tfloat ior;\n\t#endif\n\t#ifdef USE_TRANSMISSION\n\t\tfloat transmission;\n\t\tfloat transmissionAlpha;\n\t\tfloat thickness;\n\t\tfloat attenuationDistance;\n\t\tvec3 attenuationColor;\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\n#if defined( USE_SHEEN )\nfloat D_Charlie( float roughness, float dotNH ) {\n\tfloat alpha = pow2( roughness );\n\tfloat invAlpha = 1.0 / alpha;\n\tfloat cos2h = dotNH * dotNH;\n\tfloat sin2h = max( 1.0 - cos2h, 0.0078125 );\n\treturn ( 2.0 + invAlpha ) * pow( sin2h, invAlpha * 0.5 ) / ( 2.0 * PI );\n}\nfloat V_Neubelt( float dotNV, float dotNL ) {\n\treturn saturate( 1.0 / ( 4.0 * ( dotNL + dotNV - dotNL * dotNV ) ) );\n}\nvec3 BRDF_Sheen( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, vec3 sheenColor, const in float sheenRoughness ) {\n\tvec3 halfDir = normalize( lightDir + viewDir );\n\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\tfloat D = D_Charlie( sheenRoughness, dotNH );\n\tfloat V = V_Neubelt( dotNV, dotNL );\n\treturn sheenColor * ( D * V );\n}\n#endif\nfloat IBLSheenBRDF( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tfloat r2 = roughness * roughness;\n\tfloat a = roughness < 0.25 ? -339.2 * r2 + 161.4 * roughness - 25.9 : -8.48 * r2 + 14.3 * roughness - 9.95;\n\tfloat b = roughness < 0.25 ? 44.0 * r2 - 23.7 * roughness + 3.26 : 1.97 * r2 - 3.27 * roughness + 0.72;\n\tfloat DG = exp( a * dotNV + b ) + ( roughness < 0.25 ? 0.0 : 0.1 * ( roughness - 0.25 ) );\n\treturn saturate( DG * RECIPROCAL_PI );\n}\nvec2 DFGApprox( const in vec3 normal, const in vec3 viewDir, const in float roughness ) {\n\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 fab = vec2( - 1.04, 1.04 ) * a004 + r.zw;\n\treturn fab;\n}\nvec3 EnvironmentBRDF( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness ) {\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\treturn specularColor * fab.x + specularF90 * fab.y;\n}\n#ifdef USE_IRIDESCENCE\nvoid computeMultiscatteringIridescence( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float iridescence, const in vec3 iridescenceF0, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#else\nvoid computeMultiscattering( const in vec3 normal, const in vec3 viewDir, const in vec3 specularColor, const in float specularF90, const in float roughness, inout vec3 singleScatter, inout vec3 multiScatter ) {\n#endif\n\tvec2 fab = DFGApprox( normal, viewDir, roughness );\n\t#ifdef USE_IRIDESCENCE\n\t\tvec3 Fr = mix( specularColor, iridescenceF0, iridescence );\n\t#else\n\t\tvec3 Fr = specularColor;\n\t#endif\n\tvec3 FssEss = Fr * fab.x + specularF90 * fab.y;\n\tfloat Ess = fab.x + fab.y;\n\tfloat Ems = 1.0 - Ess;\n\tvec3 Favg = Fr + ( 1.0 - Fr ) * 0.047619;\tvec3 Fms = FssEss * Favg / ( 1.0 - Ems * Favg );\n\tsingleScatter += FssEss;\n\tmultiScatter += Fms * Ems;\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.roughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos + halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos - halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos - halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos + halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 irradiance, const in vec3 clearcoatRadiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, material.sheenRoughness );\n\t#endif\n\tvec3 singleScattering = vec3( 0.0 );\n\tvec3 multiScattering = vec3( 0.0 );\n\tvec3 cosineWeightedIrradiance = irradiance * RECIPROCAL_PI;\n\t#ifdef USE_IRIDESCENCE\n\t\tcomputeMultiscatteringIridescence( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.roughness, singleScattering, multiScattering );\n\t#endif\n\tvec3 totalScattering = singleScattering + multiScattering;\n\tvec3 diffuse = material.diffuseColor * ( 1.0 - max( max( totalScattering.r, totalScattering.g ), totalScattering.b ) );\n\treflectedLight.indirectSpecular += radiance * singleScattering;\n\treflectedLight.indirectSpecular += multiScattering * cosineWeightedIrradiance;\n\treflectedLight.indirectDiffuse += diffuse * cosineWeightedIrradiance;\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}";
13947 var lights_fragment_begin =
"\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\n\tif ( material.iridescenceThickness == 0.0 ) {\n\t\tmaterial.iridescence = 0.0;\n\t} else {\n\t\tmaterial.iridescence = saturate( material.iridescence );\n\t}\n\tif ( material.iridescence > 0.0 ) {\n\t\tmaterial.iridescenceFresnel = evalIridescence( 1.0, material.iridescenceIOR, dotNVi, material.iridescenceThickness, material.specularColor );\n\t\tmaterial.iridescenceF0 = Schlick_to_F0( material.iridescenceFresnel, 1.0, dotNVi );\n\t}\n#endif\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointLightInfo( pointLight, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\tvec4 spotColor;\n\tvec3 spotLightCoord;\n\tbool inSpotLightMap;\n\t#if defined( USE_SHADOWMAP ) && NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotLightInfo( spotLight, geometryPosition, directLight );\n\t\t#if ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#define SPOT_LIGHT_MAP_INDEX UNROLLED_LOOP_INDEX\n\t\t#elif ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t#define SPOT_LIGHT_MAP_INDEX NUM_SPOT_LIGHT_MAPS\n\t\t#else\n\t\t#define SPOT_LIGHT_MAP_INDEX ( UNROLLED_LOOP_INDEX - NUM_SPOT_LIGHT_SHADOWS + NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS )\n\t\t#endif\n\t\t#if ( SPOT_LIGHT_MAP_INDEX < NUM_SPOT_LIGHT_MAPS )\n\t\t\tspotLightCoord = vSpotLightCoord[ i ].xyz / vSpotLightCoord[ i ].w;\n\t\t\tinSpotLightMap = all( lessThan( abs( spotLightCoord * 2. - 1. ), vec3( 1.0 ) ) );\n\t\t\tspotColor = texture2D( spotLightMap[ SPOT_LIGHT_MAP_INDEX ], spotLightCoord.xy );\n\t\t\tdirectLight.color = inSpotLightMap ? directLight.color * spotColor.rgb : directLight.color;\n\t\t#endif\n\t\t#undef SPOT_LIGHT_MAP_INDEX\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\tspotLightShadow = spotLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#if defined( USE_SHADOWMAP ) && NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLightShadow;\n\t#endif\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalLightInfo( directionalLight, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n\t}\n\t#pragma unroll_loop_end\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 iblIrradiance = vec3( 0.0 );\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometryNormal );\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearcoatRadiance = vec3( 0.0 );\n#endif";
13949 var lights_fragment_maps =
"#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\tvec3 lightMapIrradiance = lightMapTexel.rgb * lightMapIntensity;\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( STANDARD ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tiblIrradiance += getIBLIrradiance( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif";
13951 var lights_fragment_end =
"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif";
13953 var
logdepthbuf_fragment =
"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif";
13955 var
logdepthbuf_pars_fragment =
"#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif";
13957 var
logdepthbuf_pars_vertex =
"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t\tvarying float vIsPerspective;\n\t#else\n\t\tuniform float logDepthBufFC;\n\t#endif\n#endif";
13959 var
logdepthbuf_vertex =
"#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n\t#else\n\t\tif ( isPerspectiveMatrix( projectionMatrix ) ) {\n\t\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\t\tgl_Position.z *= gl_Position.w;\n\t\t}\n\t#endif\n#endif";
13961 var
map_fragment =
"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\tsampledDiffuseColor = vec4( mix( pow( sampledDiffuseColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), sampledDiffuseColor.rgb * 0.0773993808, vec3( lessThanEqual( sampledDiffuseColor.rgb, vec3( 0.04045 ) ) ) ), sampledDiffuseColor.w );\n\t\n\t#endif\n\tdiffuseColor *= sampledDiffuseColor;\n#endif";
13965 var
map_particle_fragment =
"#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tdiffuseColor *= texture2D( map, uv );\n#endif\n#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, uv ).g;\n#endif";
13967 var
map_particle_pars_fragment =
"#if defined( USE_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\n#endif\n#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif";
13969 var metalnessmap_fragment =
"float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif";
13971 var metalnessmap_pars_fragment =
"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif";
13973 var morphcolor_vertex =
"#if defined( USE_MORPHCOLORS ) && defined( MORPHTARGETS_TEXTURE )\n\tvColor *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t#if defined( USE_COLOR_ALPHA )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ) * morphTargetInfluences[ i ];\n\t\t#elif defined( USE_COLOR )\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) vColor += getMorph( gl_VertexID, i, 2 ).rgb * morphTargetInfluences[ i ];\n\t\t#endif\n\t}\n#endif";
13975 var
morphnormal_vertex =
"#ifdef USE_MORPHNORMALS\n\tobjectNormal *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\tobjectNormal += morphNormal0 * morphTargetInfluences[ 0 ];\n\t\tobjectNormal += morphNormal1 * morphTargetInfluences[ 1 ];\n\t\tobjectNormal += morphNormal2 * morphTargetInfluences[ 2 ];\n\t\tobjectNormal += morphNormal3 * morphTargetInfluences[ 3 ];\n\t#endif\n#endif";
13977 var
morphtarget_pars_vertex =
"#ifdef USE_MORPHTARGETS\n\tuniform float morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t\tuniform sampler2DArray morphTargetsTexture;\n\t\tuniform ivec2 morphTargetsTextureSize;\n\t\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t\t}\n\t#else\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\tuniform float morphTargetInfluences[ 8 ];\n\t\t#else\n\t\t\tuniform float morphTargetInfluences[ 4 ];\n\t\t#endif\n\t#endif\n#endif";
13979 var
morphtarget_vertex =
"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\t#ifdef MORPHTARGETS_TEXTURE\n\t\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t\t}\n\t#else\n\t\ttransformed += morphTarget0 * morphTargetInfluences[ 0 ];\n\t\ttransformed += morphTarget1 * morphTargetInfluences[ 1 ];\n\t\ttransformed += morphTarget2 * morphTargetInfluences[ 2 ];\n\t\ttransformed += morphTarget3 * morphTargetInfluences[ 3 ];\n\t\t#ifndef USE_MORPHNORMALS\n\t\t\ttransformed += morphTarget4 * morphTargetInfluences[ 4 ];\n\t\t\ttransformed += morphTarget5 * morphTargetInfluences[ 5 ];\n\t\t\ttransformed += morphTarget6 * morphTargetInfluences[ 6 ];\n\t\t\ttransformed += morphTarget7 * morphTargetInfluences[ 7 ];\n\t\t#endif\n\t#endif\n#endif";
13981 var normal_fragment_begin =
"float faceDirection = gl_FrontFacing ? 1.0 : - 1.0;\n#ifdef FLAT_SHADED\n\tvec3 fdx = dFdx( vViewPosition );\n\tvec3 fdy = dFdy( vViewPosition );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;";
13983 var normal_fragment_maps =
"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\t#ifdef FLIP_SIDED\n\t\tnormal = - normal;\n\t#endif\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * faceDirection;\n\t#endif\n\tnormal = normalize( normalMatrix * normal );\n#elif defined( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( - vViewPosition, normal, dHdxy_fwd(), faceDirection );\n#endif";
13985 var normal_pars_fragment =
"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif";
13987 var normal_pars_vertex =
"#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n\t#ifdef USE_TANGENT\n\t\tvarying vec3 vTangent;\n\t\tvarying vec3 vBitangent;\n\t#endif\n#endif";
13989 var normal_vertex =
"#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n\t#ifdef USE_TANGENT\n\t\tvTangent = normalize( transformedTangent );\n\t\tvBitangent = normalize( cross( vNormal, vTangent ) * tangent.w );\n\t#endif\n#endif";
13991 var
normalmap_pars_fragment =
"#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n#endif\n#ifdef USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.st );\n\t\tvec3 N = surf_norm;\n\t\tvec3 q1perp = cross( q1, N );\n\t\tvec3 q0perp = cross( N, q0 );\n\t\tvec3 T = q1perp * st0.x + q0perp * st1.x;\n\t\tvec3 B = q1perp * st0.y + q0perp * st1.y;\n\t\tfloat det = max( dot( T, T ), dot( B, B ) );\n\t\tfloat scale = ( det == 0.0 ) ? 0.0 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif";
13993 var clearcoat_normal_fragment_begin =
"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif";
13995 var clearcoat_normal_fragment_maps =
"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif";
13997 var clearcoat_pars_fragment =
"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\n#endif";
13999 var iridescence_pars_fragment =
"#ifdef USE_IRIDESCENCEMAP\n\tuniform sampler2D iridescenceMap;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform sampler2D iridescenceThicknessMap;\n#endif";
14001 var opaque_fragment =
"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\n#endif\ngl_FragColor = vec4( outgoingLight, diffuseColor.a );";
14003 var packing =
"vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nvec2 packDepthToRG( in highp float v ) {\n\treturn packDepthToRGBA( v ).yx;\n}\nfloat unpackRGToDepth( const in highp vec2 v ) {\n\treturn unpackRGBAToDepth( vec4( v.xy, 0.0, 0.0 ) );\n}\nvec4 pack2HalfToRGBA( vec2 v ) {\n\tvec4 r = vec4( v.x, fract( v.x * 255.0 ), v.y, fract( v.y * 255.0 ) );\n\treturn vec4( r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w );\n}\nvec2 unpackRGBATo2Half( vec4 v ) {\n\treturn vec2( v.x + ( v.y / 255.0 ), v.z + ( v.w / 255.0 ) );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn depth * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( ( near + viewZ ) * far ) / ( ( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - far );\n}";
14005 var premultiplied_alpha_fragment =
"#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif";
14007 var project_vertex =
"vec4 mvPosition = vec4( transformed, 1.0 );\n#ifdef USE_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\n#ifdef USE_INSTANCING\n\tmvPosition = instanceMatrix * mvPosition;\n#endif\nmvPosition = modelViewMatrix * mvPosition;\ngl_Position = projectionMatrix * mvPosition;";
14009 var dithering_fragment =
"#ifdef DITHERING\n\tgl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif";
14011 var dithering_pars_fragment =
"#ifdef DITHERING\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif";
14013 var roughnessmap_fragment =
"float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vRoughnessMapUv );\n\troughnessFactor *= texelRoughness.g;\n#endif";
14015 var roughnessmap_pars_fragment =
"#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif";
14017 var
shadowmap_pars_fragment =
"#if NUM_SPOT_LIGHT_COORDS > 0\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#if NUM_SPOT_LIGHT_MAPS > 0\n\tuniform sampler2D spotLightMap[ NUM_SPOT_LIGHT_MAPS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHT_SHADOWS ];\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tvec2 texture2DDistribution( sampler2D shadow, vec2 uv ) {\n\t\treturn unpackRGBATo2Half( texture2D( shadow, uv ) );\n\t}\n\tfloat VSMShadow (sampler2D shadow, vec2 uv, float compare ){\n\t\tfloat occlusion = 1.0;\n\t\tvec2 distribution = texture2DDistribution( shadow, uv );\n\t\tfloat hard_shadow = step( compare , distribution.x );\n\t\tif (hard_shadow != 1.0 ) {\n\t\t\tfloat distance = compare - distribution.x ;\n\t\t\tfloat variance = max( 0.00000, distribution.y * distribution.y );\n\t\t\tfloat softness_probability = variance / (variance + distance * distance );\t\t\tsoftness_probability = clamp( ( softness_probability - 0.3 ) / ( 0.95 - 0.3 ), 0.0, 1.0 );\t\t\tocclusion = clamp( max( hard_shadow, softness_probability ), 0.0, 1.0 );\n\t\t}\n\t\treturn occlusion;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tfloat dx2 = dx0 / 2.0;\n\t\t\tfloat dy2 = dy0 / 2.0;\n\t\t\tfloat dx3 = dx1 / 2.0;\n\t\t\tfloat dy3 = dy1 / 2.0;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy2 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx2, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx3, dy3 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 17.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx = texelSize.x;\n\t\t\tfloat dy = texelSize.y;\n\t\t\tvec2 uv = shadowCoord.xy;\n\t\t\tvec2 f = fract( uv * shadowMapSize + 0.5 );\n\t\t\tuv -= f * texelSize;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, uv, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( dx, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + vec2( 0.0, dy ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, uv + texelSize, shadowCoord.z ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 0.0 ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( -dx, dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, dy ), shadowCoord.z ),\n\t\t\t\t\t f.x ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( 0.0, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 0.0, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( texture2DCompare( shadowMap, uv + vec2( dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t f.y ) +\n\t\t\t\tmix( mix( texture2DCompare( shadowMap, uv + vec2( -dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t mix( texture2DCompare( shadowMap, uv + vec2( -dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.x ),\n\t\t\t\t\t f.y )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_VSM )\n\t\t\tshadow = VSMShadow( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif";
14019 var
shadowmap_pars_vertex =
"#if NUM_SPOT_LIGHT_COORDS > 0\n\tuniform mat4 spotLightMatrix[ NUM_SPOT_LIGHT_COORDS ];\n\tvarying vec4 vSpotLightCoord[ NUM_SPOT_LIGHT_COORDS ];\n#endif\n#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHT_SHADOWS ];\n\t\tstruct DirectionalLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform DirectionalLightShadow directionalLightShadows[ NUM_DIR_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\t\tstruct SpotLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t};\n\t\tuniform SpotLightShadow spotLightShadows[ NUM_SPOT_LIGHT_SHADOWS ];\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHT_SHADOWS ];\n\t\tstruct PointLightShadow {\n\t\t\tfloat shadowBias;\n\t\t\tfloat shadowNormalBias;\n\t\t\tfloat shadowRadius;\n\t\t\tvec2 shadowMapSize;\n\t\t\tfloat shadowCameraNear;\n\t\t\tfloat shadowCameraFar;\n\t\t};\n\t\tuniform PointLightShadow pointLightShadows[ NUM_POINT_LIGHT_SHADOWS ];\n\t#endif\n#endif";
14021 var
shadowmap_vertex =
"#if ( defined( USE_SHADOWMAP ) && ( NUM_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#if NUM_SPOT_LIGHT_COORDS > 0\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_COORDS; i ++ ) {\n\t\tshadowWorldPosition = worldPosition;\n\t\t#if ( defined( USE_SHADOWMAP ) && UNROLLED_LOOP_INDEX < NUM_SPOT_LIGHT_SHADOWS )\n\t\t\tshadowWorldPosition.xyz += shadowWorldNormal * spotLightShadows[ i ].shadowNormalBias;\n\t\t#endif\n\t\tvSpotLightCoord[ i ] = spotLightMatrix[ i ] * shadowWorldPosition;\n\t}\n\t#pragma unroll_loop_end\n#endif";
14023 var shadowmask_pars_fragment =
"float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\tDirectionalLightShadow directionalLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\tdirectionalLight = directionalLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_SPOT_LIGHT_SHADOWS > 0\n\tSpotLightShadow spotLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_SPOT_LIGHT_SHADOWS; i ++ ) {\n\t\tspotLight = spotLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\tPointLightShadow pointLight;\n\t#pragma unroll_loop_start\n\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\tpointLight = pointLightShadows[ i ];\n\t\tshadow *= receiveShadow ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#pragma unroll_loop_end\n\t#endif\n\t#endif\n\treturn shadow;\n}";
14025 var
skinbase_vertex =
"#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif";
14027 var
skinning_pars_vertex =
"#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\tuniform highp sampler2D boneTexture;\n\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\n\t}\n#endif";
14029 var
skinning_vertex =
"#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif";
14031 var
skinnormal_vertex =
"#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n\t#ifdef USE_TANGENT\n\t\tobjectTangent = vec4( skinMatrix * vec4( objectTangent, 0.0 ) ).xyz;\n\t#endif\n#endif";
14033 var
specularmap_fragment =
"float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vSpecularMapUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif";
14037 var tonemapping_fragment =
"#if defined( TONE_MAPPING )\n\tgl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif";
14039 var tonemapping_pars_fragment =
"#ifndef saturate\n#define saturate( a ) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\nvec3 RRTAndODTFit( vec3 v ) {\n\tvec3 a = v * ( v + 0.0245786 ) - 0.000090537;\n\tvec3 b = v * ( 0.983729 * v + 0.4329510 ) + 0.238081;\n\treturn a / b;\n}\nvec3 ACESFilmicToneMapping( vec3 color ) {\n\tconst mat3 ACESInputMat = mat3(\n\t\tvec3( 0.59719, 0.07600, 0.02840 ),\t\tvec3( 0.35458, 0.90834, 0.13383 ),\n\t\tvec3( 0.04823, 0.01566, 0.83777 )\n\t);\n\tconst mat3 ACESOutputMat = mat3(\n\t\tvec3( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.07602 )\n\t);\n\tcolor *= toneMappingExposure / 0.6;\n\tcolor = ACESInputMat * color;\n\tcolor = RRTAndODTFit( color );\n\tcolor = ACESOutputMat * color;\n\treturn saturate( color );\n}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor *= toneMappingExposure;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\treturn color;\n}\nvec3 CustomToneMapping( vec3 color ) { return color; }";
14041 var transmission_fragment =
"#ifdef USE_TRANSMISSION\n\tmaterial.transmission = transmission;\n\tmaterial.transmissionAlpha = 1.0;\n\tmaterial.thickness = thickness;\n\tmaterial.attenuationDistance = attenuationDistance;\n\tmaterial.attenuationColor = attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tmaterial.transmission *= texture2D( transmissionMap, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.rgb, material.transmission );\n#endif";
14043 var transmission_pars_fragment =
"#ifdef USE_TRANSMISSION\n\tuniform float transmission;\n\tuniform float thickness;\n\tuniform float attenuationDistance;\n\tuniform vec3 attenuationColor;\n\t#ifdef USE_TRANSMISSIONMAP\n\t\tuniform sampler2D transmissionMap;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tuniform sampler2D thicknessMap;\n\t#endif\n\tuniform vec2 transmissionSamplerSize;\n\tuniform sampler2D transmissionSamplerMap;\n\tuniform mat4 modelMatrix;\n\tuniform mat4 projectionMatrix;\n\tvarying vec3 vWorldPosition;\n\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\n\tvec3 getVolumeTransmissionRay( const in vec3 n, const in vec3 v, const in float thickness, const in float ior, const in mat4 modelMatrix ) {\n\t\tvec3 refractionVector = refract( - v, normalize( n ), 1.0 / ior );\n\t\tvec3 modelScale;\n\t\tmodelScale.x = length( vec3( modelMatrix[ 0 ].xyz ) );\n\t\tmodelScale.y = length( vec3( modelMatrix[ 1 ].xyz ) );\n\t\tmodelScale.z = length( vec3( modelMatrix[ 2 ].xyz ) );\n\t\treturn normalize( refractionVector ) * thickness * modelScale;\n\t}\n\tfloat applyIorToRoughness( const in float roughness, const in float ior ) {\n\t\treturn roughness * clamp( ior * 2.0 - 2.0, 0.0, 1.0 );\n\t}\n\tvec4 getTransmissionSample( const in vec2 fragCoord, const in float roughness, const in float ior ) {\n\t\tfloat lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\n\t\t}\n\t}\n\tvec4 getIBLVolumeRefraction( const in vec3 n, const in vec3 v, const in float roughness, const in vec3 diffuseColor,\n\t\tconst in vec3 specularColor, const in float specularF90, const in vec3 position, const in mat4 modelMatrix,\n\t\tconst in mat4 viewMatrix, const in mat4 projMatrix, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\trefractionCoords += 1.0;\n\t\trefractionCoords /= 2.0;\n\t\tvec4 transmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\tvec3 transmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif";
14045 var uv_pars_fragment =
"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
14047 var uv_pars_vertex =
"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif";
14049 var uv_vertex =
"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 1 ) ).xy;\n#endif";
14051 var
worldpos_vertex =
"#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP ) || defined ( USE_TRANSMISSION ) || NUM_SPOT_LIGHT_COORDS > 0\n\tvec4 worldPosition = vec4( transformed, 1.0 );\n\t#ifdef USE_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\n\t#ifdef USE_INSTANCING\n\t\tworldPosition = instanceMatrix * worldPosition;\n\t#endif\n\tworldPosition = modelMatrix * worldPosition;\n#endif";
14053 const vertex$h =
"varying vec2 vUv;\nuniform mat3 uvTransform;\nvoid main() {\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\tgl_Position = vec4( position.xy, 1.0, 1.0 );\n}";
14055 const fragment$h =
"uniform sampler2D t2D;\nuniform float backgroundIntensity;\nvarying vec2 vUv;\nvoid main() {\n\tvec4 texColor = texture2D( t2D, vUv );\n\t#ifdef DECODE_VIDEO_TEXTURE\n\t\ttexColor = vec4( mix( pow( texColor.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), texColor.rgb * 0.0773993808, vec3( lessThanEqual( texColor.rgb, vec3( 0.04045 ) ) ) ), texColor.w );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
14057 const vertex$g =
"varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
14059 const fragment$g =
"#ifdef ENVMAP_TYPE_CUBE\n\tuniform samplerCube envMap;\n#elif defined( ENVMAP_TYPE_CUBE_UV )\n\tuniform sampler2D envMap;\n#endif\nuniform float flipEnvMap;\nuniform float backgroundBlurriness;\nuniform float backgroundIntensity;\nvarying vec3 vWorldDirection;\n#include <cube_uv_reflection_fragment>\nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, vWorldDirection, backgroundBlurriness );\n\t#else\n\t\tvec4 texColor = vec4( 0.0, 0.0, 0.0, 1.0 );\n\t#endif\n\ttexColor.rgb *= backgroundIntensity;\n\tgl_FragColor = texColor;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
14061 const vertex$f =
"varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}";
14063 const fragment$f =
"uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldDirection;\nvoid main() {\n\tvec4 texColor = textureCube( tCube, vec3( tFlip * vWorldDirection.x, vWorldDirection.yz ) );\n\tgl_FragColor = texColor;\n\tgl_FragColor.a *= opacity;\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
14065 const vertex$e =
"#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvHighPrecisionZW = gl_Position.zw;\n}";
14067 const fragment$e =
"#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <logdepthbuf_fragment>\n\tfloat fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( fragCoordZ );\n\t#endif\n}";
14069 const vertex$d =
"#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}";
14071 const fragment$d =
"#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}";
14073 const vertex$c =
"varying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvWorldDirection = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}";
14075 const fragment$c =
"uniform sampler2D tEquirect;\nvarying vec3 vWorldDirection;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldDirection );\n\tvec2 sampleUV = equirectUv( direction );\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n}";
14077 const vertex$b =
"uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\tvLineDistance = scale * lineDistance;\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
14079 const fragment$b =
"uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
14081 const vertex$a =
"#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#if defined ( USE_ENVMAP ) || defined ( USE_SKINNING )\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinbase_vertex>\n\t\t#include <skinnormal_vertex>\n\t\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}";
14083 const fragment$a =
"uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\tvec4 lightMapTexel = texture2D( lightMap, vLightMapUv );\n\t\treflectedLight.indirectDiffuse += lightMapTexel.rgb * lightMapIntensity * RECIPROCAL_PI;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
14085 const vertex$9 =
"#define LAMBERT\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
14087 const fragment$9 =
"#define LAMBERT\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_lambert_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_lambert_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
14089 const vertex$8 =
"#define MATCAP\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <color_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n\tvViewPosition = - mvPosition.xyz;\n}";
14091 const fragment$8 =
"#define MATCAP\nuniform vec3 diffuse;\nuniform float opacity;\nuniform sampler2D matcap;\nvarying vec3 vViewPosition;\n#include <common>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <fog_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tvec3 viewDir = normalize( vViewPosition );\n\tvec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) );\n\tvec3 y = cross( viewDir, x );\n\tvec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5;\n\t#ifdef USE_MATCAP\n\t\tvec4 matcapColor = texture2D( matcap, uv );\n\t#else\n\t\tvec4 matcapColor = vec4( vec3( mix( 0.2, 0.8, uv.y ) ), 1.0 );\n\t#endif\n\tvec3 outgoingLight = diffuseColor.rgb * matcapColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
14093 const vertex$7 =
"#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}";
14095 const fragment$7 =
"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <normal_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n\t#ifdef OPAQUE\n\t\tgl_FragColor.a = 1.0;\n\t#endif\n}";
14097 const vertex$6 =
"#define PHONG\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
14099 const fragment$6 =
"#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
14101 const vertex$5 =
"#define STANDARD\nvarying vec3 vViewPosition;\n#ifdef USE_TRANSMISSION\n\tvarying vec3 vWorldPosition;\n#endif\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n#ifdef USE_TRANSMISSION\n\tvWorldPosition = worldPosition.xyz;\n#endif\n}";
14103 const fragment$5 =
"#define STANDARD\n#ifdef PHYSICAL\n\t#define IOR\n\t#define USE_SPECULAR\n#endif\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifdef IOR\n\tuniform float ior;\n#endif\n#ifdef USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_IRIDESCENCE\n\tuniform float iridescence;\n\tuniform float iridescenceIOR;\n\tuniform float iridescenceThicknessMinimum;\n\tuniform float iridescenceThicknessMaximum;\n#endif\n#ifdef USE_SHEEN\n\tuniform vec3 sheenColor;\n\tuniform float sheenRoughness;\n\t#ifdef USE_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\n\t#endif\n#endif\nvarying vec3 vViewPosition;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <iridescence_fragment>\n#include <cube_uv_reflection_fragment>\n#include <envmap_common_pars_fragment>\n#include <envmap_physical_pars_fragment>\n#include <fog_pars_fragment>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_physical_pars_fragment>\n#include <transmission_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <clearcoat_pars_fragment>\n#include <iridescence_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <clearcoat_normal_fragment_begin>\n\t#include <clearcoat_normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 totalDiffuse = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse;\n\tvec3 totalSpecular = reflectedLight.directSpecular + reflectedLight.indirectSpecular;\n\t#include <transmission_fragment>\n\tvec3 outgoingLight = totalDiffuse + totalSpecular + totalEmissiveRadiance;\n\t#ifdef USE_SHEEN\n\t\tfloat sheenEnergyComp = 1.0 - 0.157 * max3( material.sheenColor );\n\t\toutgoingLight = outgoingLight * sheenEnergyComp + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * material.clearcoat;\n\t#endif\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
14105 const vertex$4 =
"#define TOON\nvarying vec3 vViewPosition;\n#include <common>\n#include <batching_pars_vertex>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <normal_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <normal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
14107 const fragment$4 =
"#define TOON\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <normal_pars_fragment>\n#include <lights_toon_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_toon_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}";
14109 const vertex$3 =
"uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include <color_vertex>\n\t#include <morphcolor_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\tgl_PointSize = size;\n\t#ifdef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) gl_PointSize *= ( scale / - mvPosition.z );\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}";
14111 const fragment$3 =
"uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n}";
14113 const vertex$2 =
"#include <common>\n#include <batching_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <batching_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}";
14115 const fragment$2 =
"uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <logdepthbuf_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n}";
14117 const vertex$1 =
"uniform float rotation;\nuniform vec2 center;\n#include <common>\n#include <uv_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\tvec4 mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );\n\tvec2 scale;\n\tscale.x = length( vec3( modelMatrix[ 0 ].x, modelMatrix[ 0 ].y, modelMatrix[ 0 ].z ) );\n\tscale.y = length( vec3( modelMatrix[ 1 ].x, modelMatrix[ 1 ].y, modelMatrix[ 1 ].z ) );\n\t#ifndef USE_SIZEATTENUATION\n\t\tbool isPerspective = isPerspectiveMatrix( projectionMatrix );\n\t\tif ( isPerspective ) scale *= - mvPosition.z;\n\t#endif\n\tvec2 alignedPosition = ( position.xy - ( center - vec2( 0.5 ) ) ) * scale;\n\tvec2 rotatedPosition;\n\trotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;\n\trotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;\n\tmvPosition.xy += rotatedPosition;\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}";
14119 const fragment$1 =
"uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <alphatest_pars_fragment>\n#include <alphahash_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <alphahash_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\t#include <opaque_fragment>\n\t#include <tonemapping_fragment>\n\t#include <colorspace_fragment>\n\t#include <fog_fragment>\n}";
14122 alphahash_fragment: alphahash_fragment,
14123 alphahash_pars_fragment: alphahash_pars_fragment,
14127 alphatest_pars_fragment: alphatest_pars_fragment,
14128 aomap_fragment: aomap_fragment,
14129 aomap_pars_fragment: aomap_pars_fragment,
14130 batching_pars_vertex: batching_pars_vertex,
14131 batching_vertex: batching_vertex,
14132 begin_vertex: begin_vertex,
14133 beginnormal_vertex: beginnormal_vertex,
14135 iridescence_fragment: iridescence_fragment,
14137 clipping_planes_fragment: clipping_planes_fragment,
14138 clipping_planes_pars_fragment: clipping_planes_pars_fragment,
14139 clipping_planes_pars_vertex: clipping_planes_pars_vertex,
14140 clipping_planes_vertex: clipping_planes_vertex,
14146 cube_uv_reflection_fragment: cube_uv_reflection_fragment,
14148 displacementmap_pars_vertex: displacementmap_pars_vertex,
14149 displacementmap_vertex: displacementmap_vertex,
14150 emissivemap_fragment: emissivemap_fragment,
14151 emissivemap_pars_fragment: emissivemap_pars_fragment,
14152 colorspace_fragment: colorspace_fragment,
14153 colorspace_pars_fragment: colorspace_pars_fragment,
14155 envmap_common_pars_fragment: envmap_common_pars_fragment,
14158 envmap_physical_pars_fragment: envmap_physical_pars_fragment,
14160 fog_vertex: fog_vertex,
14161 fog_pars_vertex: fog_pars_vertex,
14164 gradientmap_pars_fragment: gradientmap_pars_fragment,
14167 lights_lambert_fragment: lights_lambert_fragment,
14168 lights_lambert_pars_fragment: lights_lambert_pars_fragment,
14169 lights_pars_begin: lights_pars_begin,
14170 lights_toon_fragment: lights_toon_fragment,
14171 lights_toon_pars_fragment: lights_toon_pars_fragment,
14174 lights_physical_fragment: lights_physical_fragment,
14175 lights_physical_pars_fragment: lights_physical_pars_fragment,
14176 lights_fragment_begin: lights_fragment_begin,
14177 lights_fragment_maps: lights_fragment_maps,
14178 lights_fragment_end: lights_fragment_end,
14187 metalnessmap_fragment: metalnessmap_fragment,
14188 metalnessmap_pars_fragment: metalnessmap_pars_fragment,
14189 morphcolor_vertex: morphcolor_vertex,
14193 normal_fragment_begin: normal_fragment_begin,
14194 normal_fragment_maps: normal_fragment_maps,
14195 normal_pars_fragment: normal_pars_fragment,
14196 normal_pars_vertex: normal_pars_vertex,
14197 normal_vertex: normal_vertex,
14199 clearcoat_normal_fragment_begin: clearcoat_normal_fragment_begin,
14200 clearcoat_normal_fragment_maps: clearcoat_normal_fragment_maps,
14201 clearcoat_pars_fragment: clearcoat_pars_fragment,
14202 iridescence_pars_fragment: iridescence_pars_fragment,
14203 opaque_fragment: opaque_fragment,
14205 premultiplied_alpha_fragment: premultiplied_alpha_fragment,
14206 project_vertex: project_vertex,
14207 dithering_fragment: dithering_fragment,
14208 dithering_pars_fragment: dithering_pars_fragment,
14209 roughnessmap_fragment: roughnessmap_fragment,
14210 roughnessmap_pars_fragment: roughnessmap_pars_fragment,
14214 shadowmask_pars_fragment: shadowmask_pars_fragment,
14221 tonemapping_fragment: tonemapping_fragment,
14222 tonemapping_pars_fragment: tonemapping_pars_fragment,
14223 transmission_fragment: transmission_fragment,
14224 transmission_pars_fragment: transmission_pars_fragment,
14225 uv_pars_fragment: uv_pars_fragment,
14226 uv_pars_vertex: uv_pars_vertex,
14227 uv_vertex: uv_vertex,
14230 background_vert: vertex$h,
14231 background_frag: fragment$h,
14232 backgroundCube_vert: vertex$g,
14233 backgroundCube_frag: fragment$g,
14234 cube_vert: vertex$f,
14235 cube_frag: fragment$f,
14236 depth_vert: vertex$e,
14237 depth_frag: fragment$e,
14238 distanceRGBA_vert: vertex$d,
14239 distanceRGBA_frag: fragment$d,
14240 equirect_vert: vertex$c,
14241 equirect_frag: fragment$c,
14242 linedashed_vert: vertex$b,
14243 linedashed_frag: fragment$b,
14244 meshbasic_vert: vertex$a,
14245 meshbasic_frag: fragment$a,
14246 meshlambert_vert: vertex$9,
14247 meshlambert_frag: fragment$9,
14248 meshmatcap_vert: vertex$8,
14249 meshmatcap_frag: fragment$8,
14250 meshnormal_vert: vertex$7,
14251 meshnormal_frag: fragment$7,
14252 meshphong_vert: vertex$6,
14253 meshphong_frag: fragment$6,
14254 meshphysical_vert: vertex$5,
14255 meshphysical_frag: fragment$5,
14256 meshtoon_vert: vertex$4,
14257 meshtoon_frag: fragment$4,
14258 points_vert: vertex$3,
14259 points_frag: fragment$3,
14260 shadow_vert: vertex$2,
14261 shadow_frag: fragment$2,
14262 sprite_vert: vertex$1,
14263 sprite_frag: fragment$1
14274 diffuse: { value:
new Color( 0xffffff ) },
14275 opacity: { value: 1.0 },
14277 map: { value:
null },
14278 mapTransform: { value:
new Matrix3() },
14280 alphaMap: { value:
null },
14281 alphaMapTransform: { value:
new Matrix3() },
14283 alphaTest: { value: 0 }
14289 specularMap: { value:
null },
14290 specularMapTransform: { value:
new Matrix3() }
14296 envMap: { value:
null },
14297 flipEnvMap: { value: - 1 },
14298 reflectivity: { value: 1.0 },
14299 ior: { value: 1.5 },
14300 refractionRatio: { value: 0.98 },
14306 aoMap: { value:
null },
14307 aoMapIntensity: { value: 1 },
14308 aoMapTransform: { value:
new Matrix3() }
14314 lightMap: { value:
null },
14315 lightMapIntensity: { value: 1 },
14316 lightMapTransform: { value:
new Matrix3() }
14322 bumpMap: { value:
null },
14323 bumpMapTransform: { value:
new Matrix3() },
14324 bumpScale: { value: 1 }
14330 normalMap: { value:
null },
14331 normalMapTransform: { value:
new Matrix3() },
14332 normalScale: { value:
new Vector2( 1, 1 ) }
14338 displacementMap: { value:
null },
14339 displacementMapTransform: { value:
new Matrix3() },
14340 displacementScale: { value: 1 },
14341 displacementBias: { value: 0 }
14347 emissiveMap: { value:
null },
14348 emissiveMapTransform: { value:
new Matrix3() }
14354 metalnessMap: { value:
null },
14355 metalnessMapTransform: { value:
new Matrix3() }
14361 roughnessMap: { value:
null },
14362 roughnessMapTransform: { value:
new Matrix3() }
14368 gradientMap: { value:
null }
14374 fogDensity: { value: 0.00025 },
14375 fogNear: { value: 1 },
14376 fogFar: { value: 2000 },
14377 fogColor: { value:
new Color( 0xffffff ) }
14383 ambientLightColor: { value: [] },
14385 lightProbe: { value: [] },
14387 directionalLights: { value: [], properties: {
14392 directionalLightShadows: { value: [], properties: {
14394 shadowNormalBias: {},
14399 directionalShadowMap: { value: [] },
14400 directionalShadowMatrix: { value: [] },
14402 spotLights: { value: [], properties: {
14412 spotLightShadows: { value: [], properties: {
14414 shadowNormalBias: {},
14419 spotLightMap: { value: [] },
14420 spotShadowMap: { value: [] },
14421 spotLightMatrix: { value: [] },
14423 pointLights: { value: [], properties: {
14430 pointLightShadows: { value: [], properties: {
14432 shadowNormalBias: {},
14435 shadowCameraNear: {},
14436 shadowCameraFar: {}
14439 pointShadowMap: { value: [] },
14440 pointShadowMatrix: { value: [] },
14442 hemisphereLights: { value: [], properties: {
14449 rectAreaLights: { value: [], properties: {
14456 ltc_1: { value:
null },
14457 ltc_2: { value:
null }
14463 diffuse: { value:
new Color( 0xffffff ) },
14464 opacity: { value: 1.0 },
14465 size: { value: 1.0 },
14466 scale: { value: 1.0 },
14467 map: { value:
null },
14468 alphaMap: { value:
null },
14469 alphaMapTransform: { value:
new Matrix3() },
14470 alphaTest: { value: 0 },
14471 uvTransform: { value:
new Matrix3() }
14477 diffuse: { value:
new Color( 0xffffff ) },
14478 opacity: { value: 1.0 },
14479 center: { value:
new Vector2( 0.5, 0.5 ) },
14480 rotation: { value: 0.0 },
14481 map: { value:
null },
14482 mapTransform: { value:
new Matrix3() },
14483 alphaMap: { value:
null },
14484 alphaMapTransform: { value:
new Matrix3() },
14485 alphaTest: { value: 0 }
14495 uniforms: mergeUniforms( [
14511 uniforms: mergeUniforms( [
14524 emissive: { value: new Color( 0x000000 ) }
14535 uniforms: mergeUniforms( [
14548 emissive: { value: new Color( 0x000000 ) },
14549 specular: { value: new Color( 0x111111 ) },
14550 shininess: { value: 30 }
14561 uniforms: mergeUniforms( [
14575 emissive: { value: new Color( 0x000000 ) },
14576 roughness: { value: 1.0 },
14577 metalness: { value: 0.0 },
14578 envMapIntensity: { value: 1 }
14589 uniforms: mergeUniforms( [
14601 emissive: { value: new Color( 0x000000 ) }
14612 uniforms: mergeUniforms( [
14619 matcap: { value: null }
14630 uniforms: mergeUniforms( [
14642 uniforms: mergeUniforms( [
14646 scale: { value: 1 },
14647 dashSize: { value: 1 },
14648 totalSize: { value: 2 }
14659 uniforms: mergeUniforms( [
14671 uniforms: mergeUniforms( [
14677 opacity: { value: 1.0 }
14688 uniforms: mergeUniforms( [
14701 uvTransform: { value:
new Matrix3() },
14702 t2D: { value:
null },
14703 backgroundIntensity: { value: 1 }
14714 envMap: { value:
null },
14715 flipEnvMap: { value: - 1 },
14716 backgroundBlurriness: { value: 0 },
14717 backgroundIntensity: { value: 1 }
14728 tCube: { value:
null },
14729 tFlip: { value: - 1 },
14730 opacity: { value: 1.0 }
14741 tEquirect: { value:
null },
14751 uniforms: mergeUniforms( [
14755 referencePosition: { value: new Vector3() },
14756 nearDistance: { value: 1 },
14757 farDistance: { value: 1000 }
14768 uniforms: mergeUniforms( [
14772 color: { value: new Color( 0x00000 ) },
14773 opacity: { value: 1.0 }
14786 uniforms: mergeUniforms( [
14789 clearcoat: { value: 0 },
14790 clearcoatMap: { value: null },
14791 clearcoatMapTransform: { value: new Matrix3() },
14792 clearcoatNormalMap: { value: null },
14793 clearcoatNormalMapTransform: { value: new Matrix3() },
14794 clearcoatNormalScale: { value: new Vector2( 1, 1 ) },
14795 clearcoatRoughness: { value: 0 },
14796 clearcoatRoughnessMap: { value: null },
14797 clearcoatRoughnessMapTransform: { value: new Matrix3() },
14798 iridescence: { value: 0 },
14799 iridescenceMap: { value: null },
14800 iridescenceMapTransform: { value: new Matrix3() },
14801 iridescenceIOR: { value: 1.3 },
14802 iridescenceThicknessMinimum: { value: 100 },
14803 iridescenceThicknessMaximum: { value: 400 },
14804 iridescenceThicknessMap: { value: null },
14805 iridescenceThicknessMapTransform: { value: new Matrix3() },
14806 sheen: { value: 0 },
14807 sheenColor: { value: new Color( 0x000000 ) },
14808 sheenColorMap: { value: null },
14809 sheenColorMapTransform: { value: new Matrix3() },
14810 sheenRoughness: { value: 1 },
14811 sheenRoughnessMap: { value: null },
14812 sheenRoughnessMapTransform: { value: new Matrix3() },
14813 transmission: { value: 0 },
14814 transmissionMap: { value: null },
14815 transmissionMapTransform: { value: new Matrix3() },
14816 transmissionSamplerSize: { value: new Vector2() },
14817 transmissionSamplerMap: { value: null },
14818 thickness: { value: 0 },
14819 thicknessMap: { value: null },
14820 thicknessMapTransform: { value: new Matrix3() },
14821 attenuationDistance: { value: 0 },
14822 attenuationColor: { value: new Color( 0x000000 ) },
14823 specularColor: { value: new Color( 1, 1, 1 ) },
14824 specularColorMap: { value: null },
14825 specularColorMapTransform: { value: new Matrix3() },
14826 specularIntensity: { value: 1 },
14827 specularIntensityMap: { value: null },
14828 specularIntensityMapTransform: { value: new Matrix3() },
14829 anisotropyVector: { value: new Vector2() },
14830 anisotropyMap: { value: null },
14831 anisotropyMapTransform: { value: new Matrix3() },
14840 const _rgb = {
r: 0,
b: 0,
g: 0 };
14842 function WebGLBackground( renderer, cubemaps, cubeuvmaps, state, objects, alpha, premultipliedAlpha ) {
14844 const clearColor =
new Color( 0x000000 );
14845 let clearAlpha = alpha ===
true ? 0 : 1;
14850 let currentBackground =
null;
14851 let currentBackgroundVersion = 0;
14852 let currentTonemapping =
null;
14854 function render( renderList, scene ) {
14856 let forceClear =
false;
14857 let background = scene.isScene ===
true ? scene.background :
null;
14859 if ( background && background.isTexture ) {
14861 const usePMREM = scene.backgroundBlurriness > 0;
14862 background = ( usePMREM ? cubeuvmaps : cubemaps ).
get( background );
14866 if ( background ===
null ) {
14868 setClear( clearColor, clearAlpha );
14870 }
else if ( background && background.isColor ) {
14872 setClear( background, 1 );
14877 const environmentBlendMode = renderer.xr.getEnvironmentBlendMode();
14879 if ( environmentBlendMode ===
'additive' ) {
14881 state.buffers.color.setClear( 0, 0, 0, 1, premultipliedAlpha );
14883 }
else if ( environmentBlendMode ===
'alpha-blend' ) {
14885 state.buffers.color.setClear( 0, 0, 0, 0, premultipliedAlpha );
14889 if ( renderer.autoClear || forceClear ) {
14891 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil );
14895 if ( background && ( background.isCubeTexture || background.mapping === CubeUVReflectionMapping ) ) {
14899 boxMesh =
new Mesh(
14902 name:
'BackgroundCubeMaterial',
14903 uniforms: cloneUniforms(
ShaderLib.backgroundCube.uniforms ),
14904 vertexShader:
ShaderLib.backgroundCube.vertexShader,
14905 fragmentShader:
ShaderLib.backgroundCube.fragmentShader,
14913 boxMesh.geometry.deleteAttribute(
'normal' );
14914 boxMesh.geometry.deleteAttribute(
'uv' );
14916 boxMesh.onBeforeRender =
function ( renderer, scene, camera ) {
14918 this.matrixWorld.copyPosition( camera.matrixWorld );
14923 Object.defineProperty( boxMesh.material,
'envMap', {
14927 return this.uniforms.envMap.value;
14933 objects.update( boxMesh );
14937 boxMesh.material.uniforms.envMap.value = background;
14938 boxMesh.material.uniforms.flipEnvMap.value = ( background.isCubeTexture && background.isRenderTargetTexture === false ) ? - 1 : 1;
14939 boxMesh.material.uniforms.backgroundBlurriness.value = scene.backgroundBlurriness;
14940 boxMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14941 boxMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
14943 if ( currentBackground !== background ||
14944 currentBackgroundVersion !== background.version ||
14945 currentTonemapping !== renderer.toneMapping ) {
14947 boxMesh.material.needsUpdate =
true;
14949 currentBackground = background;
14950 currentBackgroundVersion = background.version;
14951 currentTonemapping = renderer.toneMapping;
14955 boxMesh.layers.enableAll();
14958 renderList.unshift( boxMesh, boxMesh.geometry, boxMesh.material, 0, 0,
null );
14960 }
else if ( background && background.isTexture ) {
14964 planeMesh =
new Mesh(
14967 name:
'BackgroundMaterial',
14968 uniforms: cloneUniforms(
ShaderLib.background.uniforms ),
14969 vertexShader:
ShaderLib.background.vertexShader,
14970 fragmentShader:
ShaderLib.background.fragmentShader,
14978 planeMesh.geometry.deleteAttribute(
'normal' );
14981 Object.defineProperty( planeMesh.material,
'map', {
14985 return this.uniforms.t2D.value;
14991 objects.update( planeMesh );
14995 planeMesh.material.uniforms.t2D.value = background;
14996 planeMesh.material.uniforms.backgroundIntensity.value = scene.backgroundIntensity;
14997 planeMesh.material.toneMapped = ColorManagement.getTransfer( background.colorSpace ) !== SRGBTransfer;
14999 if ( background.matrixAutoUpdate ===
true ) {
15001 background.updateMatrix();
15005 planeMesh.material.uniforms.uvTransform.value.copy( background.matrix );
15007 if ( currentBackground !== background ||
15008 currentBackgroundVersion !== background.version ||
15009 currentTonemapping !== renderer.toneMapping ) {
15011 planeMesh.material.needsUpdate =
true;
15013 currentBackground = background;
15014 currentBackgroundVersion = background.version;
15015 currentTonemapping = renderer.toneMapping;
15019 planeMesh.layers.enableAll();
15022 renderList.unshift( planeMesh, planeMesh.geometry, planeMesh.material, 0, 0,
null );
15028 function setClear( color, alpha ) {
15030 color.getRGB( _rgb, getUnlitUniformColorSpace( renderer ) );
15032 state.buffers.color.setClear( _rgb.r, _rgb.g, _rgb.b, alpha, premultipliedAlpha );
15038 getClearColor:
function () {
15043 setClearColor:
function ( color, alpha = 1 ) {
15045 clearColor.set( color );
15046 clearAlpha = alpha;
15047 setClear( clearColor, clearAlpha );
15050 getClearAlpha:
function () {
15055 setClearAlpha:
function ( alpha ) {
15057 clearAlpha = alpha;
15058 setClear( clearColor, clearAlpha );
15067 function WebGLBindingStates( gl, extensions, attributes, capabilities ) {
15069 const maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
15071 const extension = capabilities.isWebGL2 ? null : extensions.get(
'OES_vertex_array_object' );
15072 const vaoAvailable = capabilities.isWebGL2 || extension !==
null;
15074 const bindingStates = {};
15076 const defaultState = createBindingState(
null );
15077 let currentState = defaultState;
15078 let forceUpdate =
false;
15080 function setup(
object, material, program, geometry, index ) {
15082 let updateBuffers =
false;
15084 if ( vaoAvailable ) {
15086 const state = getBindingState( geometry, program, material );
15088 if ( currentState !== state ) {
15090 currentState = state;
15091 bindVertexArrayObject( currentState.object );
15095 updateBuffers = needsUpdate(
object, geometry, program, index );
15097 if ( updateBuffers ) saveCache(
object, geometry, program, index );
15101 const wireframe = ( material.wireframe === true );
15103 if ( currentState.geometry !== geometry.id ||
15104 currentState.program !== program.id ||
15105 currentState.wireframe !== wireframe ) {
15107 currentState.geometry = geometry.id;
15108 currentState.program = program.id;
15109 currentState.wireframe = wireframe;
15111 updateBuffers =
true;
15117 if ( index !==
null ) {
15119 attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
15123 if ( updateBuffers || forceUpdate ) {
15125 forceUpdate =
false;
15127 setupVertexAttributes(
object, material, program, geometry );
15129 if ( index !==
null ) {
15131 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer );
15139 function createVertexArrayObject() {
15141 if ( capabilities.isWebGL2 )
return gl.createVertexArray();
15143 return extension.createVertexArrayOES();
15147 function bindVertexArrayObject( vao ) {
15149 if ( capabilities.isWebGL2 )
return gl.bindVertexArray( vao );
15151 return extension.bindVertexArrayOES( vao );
15155 function deleteVertexArrayObject( vao ) {
15157 if ( capabilities.isWebGL2 )
return gl.deleteVertexArray( vao );
15159 return extension.deleteVertexArrayOES( vao );
15163 function getBindingState( geometry, program, material ) {
15165 const wireframe = ( material.wireframe === true );
15167 let programMap = bindingStates[ geometry.id ];
15172 bindingStates[ geometry.id ] = programMap;
15176 let stateMap = programMap[ program.id ];
15181 programMap[ program.id ] = stateMap;
15185 let state = stateMap[ wireframe ];
15189 state = createBindingState( createVertexArrayObject() );
15190 stateMap[ wireframe ] = state;
15198 function createBindingState( vao ) {
15200 const newAttributes = [];
15201 const enabledAttributes = [];
15202 const attributeDivisors = [];
15204 for ( let
i = 0;
i < maxVertexAttributes;
i ++ ) {
15206 newAttributes[
i ] = 0;
15207 enabledAttributes[
i ] = 0;
15208 attributeDivisors[
i ] = 0;
15219 newAttributes: newAttributes,
15220 enabledAttributes: enabledAttributes,
15221 attributeDivisors: attributeDivisors,
15230 function needsUpdate(
object, geometry, program, index ) {
15232 const cachedAttributes = currentState.attributes;
15233 const geometryAttributes = geometry.attributes;
15235 let attributesNum = 0;
15237 const programAttributes = program.getAttributes();
15239 for (
const name in programAttributes ) {
15241 const programAttribute = programAttributes[ name ];
15243 if ( programAttribute.location >= 0 ) {
15245 const cachedAttribute = cachedAttributes[ name ];
15246 let geometryAttribute = geometryAttributes[ name ];
15248 if ( geometryAttribute ===
undefined ) {
15250 if ( name ===
'instanceMatrix' &&
object.instanceMatrix ) geometryAttribute =
object.instanceMatrix;
15251 if ( name ===
'instanceColor' &&
object.instanceColor ) geometryAttribute =
object.instanceColor;
15255 if ( cachedAttribute ===
undefined )
return true;
15257 if ( cachedAttribute.attribute !== geometryAttribute )
return true;
15259 if ( geometryAttribute && cachedAttribute.data !== geometryAttribute.data )
return true;
15267 if ( currentState.attributesNum !== attributesNum )
return true;
15269 if ( currentState.index !== index )
return true;
15275 function saveCache(
object, geometry, program, index ) {
15278 const attributes = geometry.attributes;
15279 let attributesNum = 0;
15281 const programAttributes = program.getAttributes();
15283 for (
const name in programAttributes ) {
15285 const programAttribute = programAttributes[ name ];
15287 if ( programAttribute.location >= 0 ) {
15289 let attribute = attributes[ name ];
15293 if ( name ===
'instanceMatrix' &&
object.instanceMatrix ) attribute =
object.instanceMatrix;
15294 if ( name ===
'instanceColor' &&
object.instanceColor ) attribute =
object.instanceColor;
15299 data.attribute = attribute;
15301 if ( attribute && attribute.data ) {
15303 data.data = attribute.data;
15307 cache[ name ] = data;
15315 currentState.attributes =
cache;
15316 currentState.attributesNum = attributesNum;
15318 currentState.index = index;
15322 function initAttributes() {
15324 const newAttributes = currentState.newAttributes;
15326 for ( let
i = 0, il = newAttributes.length;
i < il;
i ++ ) {
15328 newAttributes[
i ] = 0;
15334 function enableAttribute( attribute ) {
15336 enableAttributeAndDivisor( attribute, 0 );
15340 function enableAttributeAndDivisor( attribute, meshPerAttribute ) {
15342 const newAttributes = currentState.newAttributes;
15343 const enabledAttributes = currentState.enabledAttributes;
15344 const attributeDivisors = currentState.attributeDivisors;
15346 newAttributes[ attribute ] = 1;
15348 if ( enabledAttributes[ attribute ] === 0 ) {
15350 gl.enableVertexAttribArray( attribute );
15351 enabledAttributes[ attribute ] = 1;
15355 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) {
15357 const extension = capabilities.isWebGL2 ? gl : extensions.get(
'ANGLE_instanced_arrays' );
15359 extension[ capabilities.isWebGL2 ?
'vertexAttribDivisor' :
'vertexAttribDivisorANGLE' ]( attribute, meshPerAttribute );
15360 attributeDivisors[ attribute ] = meshPerAttribute;
15366 function disableUnusedAttributes() {
15368 const newAttributes = currentState.newAttributes;
15369 const enabledAttributes = currentState.enabledAttributes;
15371 for ( let
i = 0, il = enabledAttributes.length;
i < il;
i ++ ) {
15373 if ( enabledAttributes[
i ] !== newAttributes[
i ] ) {
15375 gl.disableVertexAttribArray(
i );
15376 enabledAttributes[
i ] = 0;
15384 function vertexAttribPointer( index, size, type, normalized, stride, offset, integer ) {
15386 if ( integer ===
true ) {
15388 gl.vertexAttribIPointer( index, size, type, stride, offset );
15392 gl.vertexAttribPointer( index, size, type, normalized, stride, offset );
15398 function setupVertexAttributes(
object, material, program, geometry ) {
15400 if ( capabilities.isWebGL2 ===
false && (
object.isInstancedMesh || geometry.isInstancedBufferGeometry ) ) {
15402 if ( extensions.get(
'ANGLE_instanced_arrays' ) ===
null )
return;
15408 const geometryAttributes = geometry.attributes;
15410 const programAttributes = program.getAttributes();
15412 const materialDefaultAttributeValues = material.defaultAttributeValues;
15414 for (
const name in programAttributes ) {
15416 const programAttribute = programAttributes[ name ];
15418 if ( programAttribute.location >= 0 ) {
15420 let geometryAttribute = geometryAttributes[ name ];
15422 if ( geometryAttribute ===
undefined ) {
15424 if ( name ===
'instanceMatrix' &&
object.instanceMatrix ) geometryAttribute =
object.instanceMatrix;
15425 if ( name ===
'instanceColor' &&
object.instanceColor ) geometryAttribute =
object.instanceColor;
15429 if ( geometryAttribute !==
undefined ) {
15431 const normalized = geometryAttribute.normalized;
15432 const size = geometryAttribute.itemSize;
15434 const attribute = attributes.get( geometryAttribute );
15438 if ( attribute ===
undefined )
continue;
15440 const buffer = attribute.buffer;
15441 const type = attribute.type;
15442 const bytesPerElement = attribute.bytesPerElement;
15446 const integer = ( capabilities.isWebGL2 ===
true && ( type === gl.INT || type === gl.UNSIGNED_INT || geometryAttribute.gpuType ===
IntType ) );
15448 if ( geometryAttribute.isInterleavedBufferAttribute ) {
15450 const data = geometryAttribute.data;
15451 const stride = data.stride;
15452 const offset = geometryAttribute.offset;
15454 if ( data.isInstancedInterleavedBuffer ) {
15456 for ( let
i = 0;
i < programAttribute.locationSize;
i ++ ) {
15458 enableAttributeAndDivisor( programAttribute.location +
i, data.meshPerAttribute );
15462 if (
object.isInstancedMesh !==
true && geometry._maxInstanceCount ===
undefined ) {
15464 geometry._maxInstanceCount = data.meshPerAttribute * data.count;
15470 for ( let
i = 0;
i < programAttribute.locationSize;
i ++ ) {
15472 enableAttribute( programAttribute.location +
i );
15478 gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
15480 for ( let
i = 0;
i < programAttribute.locationSize;
i ++ ) {
15482 vertexAttribPointer(
15483 programAttribute.location +
i,
15484 size / programAttribute.locationSize,
15487 stride * bytesPerElement,
15488 ( offset + ( size / programAttribute.locationSize ) *
i ) * bytesPerElement,
15496 if ( geometryAttribute.isInstancedBufferAttribute ) {
15498 for ( let
i = 0;
i < programAttribute.locationSize;
i ++ ) {
15500 enableAttributeAndDivisor( programAttribute.location +
i, geometryAttribute.meshPerAttribute );
15504 if (
object.isInstancedMesh !==
true && geometry._maxInstanceCount ===
undefined ) {
15506 geometry._maxInstanceCount = geometryAttribute.meshPerAttribute * geometryAttribute.count;
15512 for ( let
i = 0;
i < programAttribute.locationSize;
i ++ ) {
15514 enableAttribute( programAttribute.location +
i );
15520 gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
15522 for ( let
i = 0;
i < programAttribute.locationSize;
i ++ ) {
15524 vertexAttribPointer(
15525 programAttribute.location +
i,
15526 size / programAttribute.locationSize,
15529 size * bytesPerElement,
15530 ( size / programAttribute.locationSize ) *
i * bytesPerElement,
15538 }
else if ( materialDefaultAttributeValues !==
undefined ) {
15540 const value = materialDefaultAttributeValues[ name ];
15544 switch ( value.length ) {
15547 gl.vertexAttrib2fv( programAttribute.location, value );
15551 gl.vertexAttrib3fv( programAttribute.location, value );
15555 gl.vertexAttrib4fv( programAttribute.location, value );
15559 gl.vertexAttrib1fv( programAttribute.location, value );
15571 disableUnusedAttributes();
15579 for (
const geometryId in bindingStates ) {
15581 const programMap = bindingStates[ geometryId ];
15583 for (
const programId in programMap ) {
15585 const stateMap = programMap[ programId ];
15587 for (
const wireframe in stateMap ) {
15589 deleteVertexArrayObject( stateMap[ wireframe ].
object );
15591 delete stateMap[ wireframe ];
15595 delete programMap[ programId ];
15599 delete bindingStates[ geometryId ];
15605 function releaseStatesOfGeometry( geometry ) {
15607 if ( bindingStates[ geometry.id ] ===
undefined )
return;
15609 const programMap = bindingStates[ geometry.id ];
15611 for (
const programId in programMap ) {
15613 const stateMap = programMap[ programId ];
15615 for (
const wireframe in stateMap ) {
15617 deleteVertexArrayObject( stateMap[ wireframe ].
object );
15619 delete stateMap[ wireframe ];
15623 delete programMap[ programId ];
15627 delete bindingStates[ geometry.id ];
15631 function releaseStatesOfProgram( program ) {
15633 for (
const geometryId in bindingStates ) {
15635 const programMap = bindingStates[ geometryId ];
15637 if ( programMap[ program.id ] ===
undefined )
continue;
15639 const stateMap = programMap[ program.id ];
15641 for (
const wireframe in stateMap ) {
15643 deleteVertexArrayObject( stateMap[ wireframe ].
object );
15645 delete stateMap[ wireframe ];
15649 delete programMap[ program.id ];
15657 resetDefaultState();
15658 forceUpdate =
true;
15660 if ( currentState === defaultState )
return;
15662 currentState = defaultState;
15663 bindVertexArrayObject( currentState.object );
15669 function resetDefaultState() {
15671 defaultState.geometry =
null;
15672 defaultState.program =
null;
15673 defaultState.wireframe =
false;
15681 resetDefaultState: resetDefaultState,
15683 releaseStatesOfGeometry: releaseStatesOfGeometry,
15684 releaseStatesOfProgram: releaseStatesOfProgram,
15686 initAttributes: initAttributes,
15687 enableAttribute: enableAttribute,
15688 disableUnusedAttributes: disableUnusedAttributes
15694 function WebGLBufferRenderer( gl, extensions, info, capabilities ) {
15696 const isWebGL2 = capabilities.isWebGL2;
15700 function setMode( value ) {
15706 function render( start, count ) {
15708 gl.drawArrays( mode, start, count );
15710 info.update( count, mode, 1 );
15714 function renderInstances( start, count, primcount ) {
15716 if ( primcount === 0 )
return;
15718 let extension, methodName;
15723 methodName =
'drawArraysInstanced';
15727 extension = extensions.get(
'ANGLE_instanced_arrays' );
15728 methodName =
'drawArraysInstancedANGLE';
15730 if ( extension ===
null ) {
15732 console.error(
'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
15739 extension[ methodName ]( mode, start, count, primcount );
15741 info.update( count, mode, primcount );
15745 function renderMultiDraw( starts, counts, drawCount ) {
15747 if ( drawCount === 0 )
return;
15749 const extension = extensions.get(
'WEBGL_multi_draw' );
15750 if ( extension ===
null ) {
15752 for ( let
i = 0;
i < drawCount;
i ++ ) {
15754 this.render( starts[
i ], counts[
i ] );
15760 extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount );
15762 let elementCount = 0;
15763 for ( let
i = 0;
i < drawCount;
i ++ ) {
15765 elementCount += counts[
i ];
15769 info.update( elementCount, mode, 1 );
15777 this.setMode = setMode;
15778 this.render = render;
15779 this.renderInstances = renderInstances;
15780 this.renderMultiDraw = renderMultiDraw;
15784 function WebGLCapabilities( gl, extensions, parameters ) {
15788 function getMaxAnisotropy() {
15790 if ( maxAnisotropy !==
undefined )
return maxAnisotropy;
15792 if ( extensions.has(
'EXT_texture_filter_anisotropic' ) ===
true ) {
15794 const extension = extensions.get(
'EXT_texture_filter_anisotropic' );
15796 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT );
15804 return maxAnisotropy;
15808 function getMaxPrecision( precision ) {
15810 if ( precision ===
'highp' ) {
15812 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 &&
15813 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) {
15819 precision =
'mediump';
15823 if ( precision ===
'mediump' ) {
15825 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 &&
15826 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) {
15838 const isWebGL2 = typeof WebGL2RenderingContext !==
'undefined' && gl.constructor.name ===
'WebGL2RenderingContext';
15840 let precision = parameters.precision !==
undefined ? parameters.precision :
'highp';
15841 const maxPrecision = getMaxPrecision( precision );
15843 if ( maxPrecision !== precision ) {
15845 console.warn(
'THREE.WebGLRenderer:', precision,
'not supported, using', maxPrecision,
'instead.' );
15846 precision = maxPrecision;
15850 const drawBuffers = isWebGL2 || extensions.has(
'WEBGL_draw_buffers' );
15852 const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer ===
true;
15854 const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
15855 const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
15856 const maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE );
15857 const maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE );
15859 const maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS );
15860 const maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS );
15861 const maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS );
15862 const maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS );
15864 const vertexTextures = maxVertexTextures > 0;
15865 const floatFragmentTextures = isWebGL2 || extensions.has(
'OES_texture_float' );
15866 const floatVertexTextures = vertexTextures && floatFragmentTextures;
15868 const maxSamples = isWebGL2 ? gl.getParameter( gl.MAX_SAMPLES ) : 0;
15872 isWebGL2: isWebGL2,
15874 drawBuffers: drawBuffers,
15876 getMaxAnisotropy: getMaxAnisotropy,
15877 getMaxPrecision: getMaxPrecision,
15879 precision: precision,
15880 logarithmicDepthBuffer: logarithmicDepthBuffer,
15882 maxTextures: maxTextures,
15883 maxVertexTextures: maxVertexTextures,
15884 maxTextureSize: maxTextureSize,
15885 maxCubemapSize: maxCubemapSize,
15887 maxAttributes: maxAttributes,
15888 maxVertexUniforms: maxVertexUniforms,
15889 maxVaryings: maxVaryings,
15890 maxFragmentUniforms: maxFragmentUniforms,
15892 vertexTextures: vertexTextures,
15893 floatFragmentTextures: floatFragmentTextures,
15894 floatVertexTextures: floatVertexTextures,
15896 maxSamples: maxSamples
15902 function WebGLClipping( properties ) {
15904 const scope =
this;
15906 let globalState =
null,
15907 numGlobalPlanes = 0,
15908 localClippingEnabled =
false,
15909 renderingShadows =
false;
15911 const plane =
new Plane(),
15912 viewNormalMatrix =
new Matrix3(),
15914 uniform = { value:
null, needsUpdate:
false };
15916 this.uniform = uniform;
15917 this.numPlanes = 0;
15918 this.numIntersection = 0;
15920 this.init =
function ( planes, enableLocalClipping ) {
15923 planes.length !== 0 ||
15924 enableLocalClipping ||
15927 numGlobalPlanes !== 0 ||
15928 localClippingEnabled;
15930 localClippingEnabled = enableLocalClipping;
15932 numGlobalPlanes = planes.length;
15938 this.beginShadows =
function () {
15940 renderingShadows =
true;
15941 projectPlanes(
null );
15945 this.endShadows =
function () {
15947 renderingShadows =
false;
15951 this.setGlobalState =
function ( planes, camera ) {
15953 globalState = projectPlanes( planes, camera, 0 );
15957 this.setState =
function ( material, camera, useCache ) {
15959 const planes = material.clippingPlanes,
15960 clipIntersection = material.clipIntersection,
15961 clipShadows = material.clipShadows;
15963 const materialProperties = properties.get( material );
15965 if ( ! localClippingEnabled || planes ===
null || planes.length === 0 || renderingShadows && ! clipShadows ) {
15969 if ( renderingShadows ) {
15973 projectPlanes(
null );
15977 resetGlobalState();
15983 const nGlobal = renderingShadows ? 0 : numGlobalPlanes,
15984 lGlobal = nGlobal * 4;
15986 let dstArray = materialProperties.clippingState ||
null;
15988 uniform.value = dstArray;
15990 dstArray = projectPlanes( planes, camera, lGlobal, useCache );
15992 for ( let
i = 0;
i !== lGlobal; ++
i ) {
15994 dstArray[
i ] = globalState[
i ];
15998 materialProperties.clippingState = dstArray;
15999 this.numIntersection = clipIntersection ? this.numPlanes : 0;
16000 this.numPlanes += nGlobal;
16007 function resetGlobalState() {
16009 if ( uniform.value !== globalState ) {
16011 uniform.value = globalState;
16012 uniform.needsUpdate = numGlobalPlanes > 0;
16016 scope.numPlanes = numGlobalPlanes;
16017 scope.numIntersection = 0;
16021 function projectPlanes( planes, camera, dstOffset, skipTransform ) {
16023 const nPlanes = planes !==
null ? planes.length : 0;
16024 let dstArray =
null;
16026 if ( nPlanes !== 0 ) {
16028 dstArray = uniform.value;
16030 if ( skipTransform !==
true || dstArray ===
null ) {
16032 const flatSize = dstOffset + nPlanes * 4,
16033 viewMatrix = camera.matrixWorldInverse;
16035 viewNormalMatrix.getNormalMatrix( viewMatrix );
16037 if ( dstArray ===
null || dstArray.length < flatSize ) {
16043 for ( let
i = 0, i4 = dstOffset;
i !== nPlanes; ++
i, i4 += 4 ) {
16045 plane.copy( planes[
i ] ).applyMatrix4( viewMatrix, viewNormalMatrix );
16047 plane.normal.toArray( dstArray, i4 );
16048 dstArray[ i4 + 3 ] = plane.constant;
16054 uniform.value = dstArray;
16055 uniform.needsUpdate =
true;
16059 scope.numPlanes = nPlanes;
16060 scope.numIntersection = 0;
16068 function WebGLCubeMaps( renderer ) {
16070 let cubemaps =
new WeakMap();
16072 function mapTextureMapping( texture, mapping ) {
16074 if ( mapping === EquirectangularReflectionMapping ) {
16078 }
else if ( mapping === EquirectangularRefractionMapping ) {
16088 function get( texture ) {
16090 if ( texture && texture.isTexture ) {
16092 const mapping = texture.mapping;
16094 if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) {
16096 if ( cubemaps.has( texture ) ) {
16098 const cubemap = cubemaps.get( texture ).texture;
16099 return mapTextureMapping( cubemap, texture.mapping );
16103 const image = texture.image;
16105 if ( image && image.height > 0 ) {
16107 const renderTarget =
new WebGLCubeRenderTarget( image.height / 2 );
16108 renderTarget.fromEquirectangularTexture( renderer, texture );
16109 cubemaps.set( texture, renderTarget );
16111 texture.addEventListener(
'dispose', onTextureDispose );
16113 return mapTextureMapping( renderTarget.texture, texture.mapping );
16133 function onTextureDispose( event ) {
16135 const texture =
event.target;
16137 texture.removeEventListener(
'dispose', onTextureDispose );
16139 const cubemap = cubemaps.get( texture );
16143 cubemaps.delete( texture );
16152 cubemaps =
new WeakMap();
16165 constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) {
16169 this.isOrthographicCamera =
true;
16171 this.type =
'OrthographicCamera';
16177 this.right = right;
16179 this.bottom = bottom;
16188 copy( source, recursive ) {
16190 super.copy( source, recursive );
16192 this.left = source.left;
16193 this.right = source.right;
16194 this.top = source.top;
16195 this.bottom = source.bottom;
16196 this.near = source.near;
16197 this.far = source.far;
16199 this.zoom = source.zoom;
16200 this.view = source.view ===
null ? null : Object.assign( {}, source.view );
16208 if ( this.view ===
null ) {
16222 this.view.enabled =
true;
16223 this.view.fullWidth = fullWidth;
16224 this.view.fullHeight = fullHeight;
16225 this.view.offsetX =
x;
16226 this.view.offsetY =
y;
16227 this.view.width = width;
16228 this.view.height = height;
16234 clearViewOffset() {
16236 if ( this.view !==
null ) {
16238 this.view.enabled =
false;
16248 const dx = ( this.right - this.left ) / ( 2 * this.zoom );
16249 const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
16250 const cx = ( this.right + this.left ) / 2;
16251 const cy = ( this.top + this.bottom ) / 2;
16253 let left = cx - dx;
16254 let right = cx + dx;
16256 let bottom = cy - dy;
16258 if ( this.view !==
null && this.view.enabled ) {
16260 const scaleW = ( this.right - this.left ) / this.view.fullWidth /
this.zoom;
16261 const scaleH = ( this.top - this.bottom ) / this.view.fullHeight /
this.zoom;
16263 left += scaleW * this.view.offsetX;
16264 right = left + scaleW * this.view.width;
16265 top -= scaleH * this.view.offsetY;
16266 bottom = top - scaleH * this.view.height;
16270 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem );
16272 this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
16278 const data = super.toJSON( meta );
16280 data.object.zoom = this.zoom;
16281 data.object.left = this.left;
16282 data.object.right = this.right;
16283 data.object.top = this.top;
16284 data.object.bottom = this.bottom;
16285 data.object.near = this.near;
16286 data.object.far = this.far;
16288 if ( this.view !==
null ) data.object.view = Object.assign( {}, this.view );
16302 const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
16306 const MAX_SAMPLES = 20;
16309 const _clearColor =
new Color();
16310 let _oldTarget =
null;
16311 let _oldActiveCubeFace = 0;
16312 let _oldActiveMipmapLevel = 0;
16315 const PHI = ( 1 +
Math.sqrt( 5 ) ) / 2;
16316 const INV_PHI = 1 / PHI;
16320 const _axisDirections = [
16325 new Vector3( 0, PHI, INV_PHI ),
16326 new Vector3( 0, PHI, - INV_PHI ),
16327 new Vector3( INV_PHI, 0, PHI ),
16328 new Vector3( - INV_PHI, 0, PHI ),
16329 new Vector3( PHI, INV_PHI, 0 ),
16330 new Vector3( - PHI, INV_PHI, 0 ) ];
16347 class PMREMGenerator {
16349 constructor( renderer ) {
16351 this._renderer = renderer;
16352 this._pingPongRenderTarget =
null;
16355 this._cubeSize = 0;
16356 this._lodPlanes = [];
16357 this._sizeLods = [];
16360 this._blurMaterial =
null;
16361 this._cubemapMaterial =
null;
16362 this._equirectMaterial =
null;
16364 this._compileMaterial( this._blurMaterial );
16375 fromScene( scene, sigma = 0, near = 0.1, far = 100 ) {
16377 _oldTarget = this._renderer.getRenderTarget();
16378 _oldActiveCubeFace = this._renderer.getActiveCubeFace();
16379 _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
16381 this._setSize( 256 );
16383 const cubeUVRenderTarget = this._allocateTargets();
16384 cubeUVRenderTarget.depthBuffer =
true;
16386 this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
16390 this._blur( cubeUVRenderTarget, 0, 0, sigma );
16394 this._applyPMREM( cubeUVRenderTarget );
16395 this._cleanup( cubeUVRenderTarget );
16397 return cubeUVRenderTarget;
16406 fromEquirectangular( equirectangular, renderTarget =
null ) {
16408 return this._fromTexture( equirectangular, renderTarget );
16417 fromCubemap( cubemap, renderTarget =
null ) {
16419 return this._fromTexture( cubemap, renderTarget );
16427 compileCubemapShader() {
16429 if ( this._cubemapMaterial ===
null ) {
16431 this._cubemapMaterial = _getCubemapMaterial();
16432 this._compileMaterial( this._cubemapMaterial );
16442 compileEquirectangularShader() {
16444 if ( this._equirectMaterial ===
null ) {
16446 this._equirectMaterial = _getEquirectMaterial();
16447 this._compileMaterial( this._equirectMaterial );
16462 if ( this._cubemapMaterial !==
null ) this._cubemapMaterial.dispose();
16463 if ( this._equirectMaterial !==
null ) this._equirectMaterial.dispose();
16469 _setSize( cubeSize ) {
16471 this._lodMax =
Math.floor(
Math.log2( cubeSize ) );
16472 this._cubeSize =
Math.pow( 2, this._lodMax );
16478 if ( this._blurMaterial !==
null ) this._blurMaterial.dispose();
16480 if ( this._pingPongRenderTarget !==
null ) this._pingPongRenderTarget.dispose();
16482 for ( let
i = 0;
i < this._lodPlanes.length;
i ++ ) {
16484 this._lodPlanes[
i ].dispose();
16490 _cleanup( outputTarget ) {
16492 this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel );
16493 outputTarget.scissorTest =
false;
16494 _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height );
16498 _fromTexture( texture, renderTarget ) {
16502 this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) );
16506 this._setSize( texture.image.width / 4 );
16510 _oldTarget = this._renderer.getRenderTarget();
16511 _oldActiveCubeFace = this._renderer.getActiveCubeFace();
16512 _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel();
16514 const cubeUVRenderTarget = renderTarget || this._allocateTargets();
16515 this._textureToCubeUV( texture, cubeUVRenderTarget );
16516 this._applyPMREM( cubeUVRenderTarget );
16517 this._cleanup( cubeUVRenderTarget );
16519 return cubeUVRenderTarget;
16523 _allocateTargets() {
16525 const width = 3 *
Math.max( this._cubeSize, 16 * 7 );
16526 const height = 4 * this._cubeSize;
16531 generateMipmaps:
false,
16532 type: HalfFloatType,
16534 colorSpace: LinearSRGBColorSpace,
16538 const cubeUVRenderTarget = _createRenderTarget( width, height, params );
16540 if ( this._pingPongRenderTarget ===
null || this._pingPongRenderTarget.width !== width ||
this._pingPongRenderTarget.height !== height ) {
16542 if ( this._pingPongRenderTarget !==
null ) {
16548 this._pingPongRenderTarget = _createRenderTarget( width, height, params );
16550 const { _lodMax } =
this;
16551 ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas } = _createPlanes( _lodMax ) );
16553 this._blurMaterial = _getBlurShader( _lodMax, width, height );
16557 return cubeUVRenderTarget;
16561 _compileMaterial( material ) {
16563 const tmpMesh =
new Mesh( this._lodPlanes[ 0 ], material );
16564 this._renderer.compile( tmpMesh, _flatCamera );
16568 _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
16573 const upSign = [ 1, - 1, 1, 1, 1, 1 ];
16574 const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ];
16575 const renderer = this._renderer;
16577 const originalAutoClear = renderer.autoClear;
16578 const toneMapping = renderer.toneMapping;
16579 renderer.getClearColor( _clearColor );
16581 renderer.toneMapping = NoToneMapping;
16582 renderer.autoClear =
false;
16585 name:
'PMREM.Background',
16591 const backgroundBox =
new Mesh(
new BoxGeometry(), backgroundMaterial );
16593 let useSolidColor =
false;
16594 const background = scene.background;
16596 if ( background ) {
16598 if ( background.isColor ) {
16600 backgroundMaterial.color.copy( background );
16601 scene.background =
null;
16602 useSolidColor =
true;
16608 backgroundMaterial.color.copy( _clearColor );
16609 useSolidColor =
true;
16613 for ( let
i = 0;
i < 6;
i ++ ) {
16619 cubeCamera.up.set( 0, upSign[
i ], 0 );
16620 cubeCamera.lookAt( forwardSign[
i ], 0, 0 );
16622 }
else if ( col === 1 ) {
16624 cubeCamera.up.set( 0, 0, upSign[
i ] );
16625 cubeCamera.lookAt( 0, forwardSign[
i ], 0 );
16629 cubeCamera.up.set( 0, upSign[
i ], 0 );
16630 cubeCamera.lookAt( 0, 0, forwardSign[
i ] );
16634 const size = this._cubeSize;
16636 _setViewport( cubeUVRenderTarget, col * size,
i > 2 ? size : 0, size, size );
16638 renderer.setRenderTarget( cubeUVRenderTarget );
16640 if ( useSolidColor ) {
16642 renderer.render( backgroundBox, cubeCamera );
16646 renderer.render( scene, cubeCamera );
16650 backgroundBox.geometry.dispose();
16651 backgroundBox.material.dispose();
16653 renderer.toneMapping = toneMapping;
16654 renderer.autoClear = originalAutoClear;
16655 scene.background = background;
16659 _textureToCubeUV( texture, cubeUVRenderTarget ) {
16661 const renderer = this._renderer;
16665 if ( isCubeTexture ) {
16667 if ( this._cubemapMaterial ===
null ) {
16669 this._cubemapMaterial = _getCubemapMaterial();
16673 this._cubemapMaterial.uniforms.flipEnvMap.value = ( texture.isRenderTargetTexture === false ) ? - 1 : 1;
16677 if ( this._equirectMaterial ===
null ) {
16679 this._equirectMaterial = _getEquirectMaterial();
16685 const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial;
16686 const mesh =
new Mesh( this._lodPlanes[ 0 ], material );
16688 const uniforms = material.uniforms;
16690 uniforms[
'envMap' ].value = texture;
16692 const size = this._cubeSize;
16694 _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size );
16696 renderer.setRenderTarget( cubeUVRenderTarget );
16697 renderer.render( mesh, _flatCamera );
16701 _applyPMREM( cubeUVRenderTarget ) {
16703 const renderer = this._renderer;
16704 const autoClear = renderer.autoClear;
16705 renderer.autoClear =
false;
16707 for ( let
i = 1;
i < this._lodPlanes.length;
i ++ ) {
16709 const sigma =
Math.sqrt( this._sigmas[
i ] * this._sigmas[
i ] - this._sigmas[
i - 1 ] * this._sigmas[
i - 1 ] );
16711 const poleAxis = _axisDirections[ (
i - 1 ) % _axisDirections.length ];
16713 this._blur( cubeUVRenderTarget,
i - 1,
i, sigma, poleAxis );
16717 renderer.autoClear = autoClear;
16728 _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
16730 const pingPongRenderTarget = this._pingPongRenderTarget;
16733 cubeUVRenderTarget,
16734 pingPongRenderTarget,
16742 pingPongRenderTarget,
16743 cubeUVRenderTarget,
16752 _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
16754 const renderer = this._renderer;
16755 const blurMaterial = this._blurMaterial;
16757 if ( direction !==
'latitudinal' && direction !==
'longitudinal' ) {
16760 'blur direction must be either latitudinal or longitudinal!' );
16765 const STANDARD_DEVIATIONS = 3;
16767 const blurMesh =
new Mesh( this._lodPlanes[ lodOut ], blurMaterial );
16768 const blurUniforms = blurMaterial.uniforms;
16770 const pixels = this._sizeLods[ lodIn ] - 1;
16771 const radiansPerPixel = isFinite( sigmaRadians ) ?
Math.PI / ( 2 * pixels ) : 2 *
Math.PI / ( 2 * MAX_SAMPLES - 1 );
16772 const sigmaPixels = sigmaRadians / radiansPerPixel;
16773 const samples = isFinite( sigmaRadians ) ? 1 +
Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
16775 if ( samples > MAX_SAMPLES ) {
16777 console.warn( `sigmaRadians,
${
16778 sigmaRadians}, is too large and will clip, as
it requested
${
16779 samples} samples when the maximum is
set to
${MAX_SAMPLES}` );
16783 const weights = [];
16786 for ( let
i = 0;
i < MAX_SAMPLES; ++
i ) {
16788 const x =
i / sigmaPixels;
16789 const weight =
Math.exp( -
x *
x / 2 );
16790 weights.push( weight );
16796 }
else if (
i < samples ) {
16804 for ( let
i = 0;
i < weights.length;
i ++ ) {
16806 weights[
i ] = weights[
i ] / sum;
16810 blurUniforms[
'envMap' ].value = targetIn.texture;
16811 blurUniforms[
'samples' ].value = samples;
16812 blurUniforms[
'weights' ].value = weights;
16813 blurUniforms[
'latitudinal' ].value = direction ===
'latitudinal';
16817 blurUniforms[
'poleAxis' ].value = poleAxis;
16821 const { _lodMax } =
this;
16822 blurUniforms[
'dTheta' ].value = radiansPerPixel;
16823 blurUniforms[
'mipInt' ].value = _lodMax - lodIn;
16825 const outputSize = this._sizeLods[ lodOut ];
16826 const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 );
16827 const y = 4 * ( this._cubeSize - outputSize );
16829 _setViewport( targetOut,
x,
y, 3 * outputSize, 2 * outputSize );
16830 renderer.setRenderTarget( targetOut );
16831 renderer.render( blurMesh, _flatCamera );
16839 function _createPlanes( lodMax ) {
16841 const lodPlanes = [];
16842 const sizeLods = [];
16847 const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
16849 for ( let
i = 0;
i < totalLods;
i ++ ) {
16851 const sizeLod =
Math.pow( 2, lod );
16852 sizeLods.push( sizeLod );
16853 let sigma = 1.0 / sizeLod;
16855 if (
i > lodMax - LOD_MIN ) {
16857 sigma = EXTRA_LOD_SIGMA[
i - lodMax + LOD_MIN - 1 ];
16859 }
else if (
i === 0 ) {
16865 sigmas.push( sigma );
16867 const texelSize = 1.0 / ( sizeLod - 2 );
16868 const min = - texelSize;
16869 const max = 1 + texelSize;
16870 const uv1 = [
min,
min,
max,
min,
max,
max,
min,
min,
max,
max,
min,
max ];
16872 const cubeFaces = 6;
16873 const vertices = 6;
16874 const positionSize = 3;
16876 const faceIndexSize = 1;
16879 const uv =
new Float32Array( uvSize * vertices * cubeFaces );
16880 const faceIndex =
new Float32Array( faceIndexSize * vertices * cubeFaces );
16882 for ( let face = 0; face < cubeFaces; face ++ ) {
16884 const x = ( face % 3 ) * 2 / 3 - 1;
16885 const y = face > 2 ? 0 : - 1;
16886 const coordinates = [
16889 x + 2 / 3,
y + 1, 0,
16891 x + 2 / 3,
y + 1, 0,
16894 position.set( coordinates, positionSize * vertices * face );
16895 uv.set( uv1, uvSize * vertices * face );
16896 const fill = [ face, face, face, face, face, face ];
16897 faceIndex.set( fill, faceIndexSize * vertices * face );
16904 planes.setAttribute(
'faceIndex',
new BufferAttribute( faceIndex, faceIndexSize ) );
16905 lodPlanes.push( planes );
16907 if ( lod > LOD_MIN ) {
16915 return { lodPlanes, sizeLods, sigmas };
16919 function _createRenderTarget( width, height, params ) {
16922 cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping;
16923 cubeUVRenderTarget.texture.name =
'PMREM.cubeUv';
16924 cubeUVRenderTarget.scissorTest =
true;
16925 return cubeUVRenderTarget;
16929 function _setViewport( target,
x,
y, width, height ) {
16931 target.viewport.set(
x,
y, width, height );
16932 target.scissor.set(
x,
y, width, height );
16936 function _getBlurShader( lodMax, width, height ) {
16939 const poleAxis =
new Vector3( 0, 1, 0 );
16942 name:
'SphericalGaussianBlur',
16946 'CUBEUV_TEXEL_WIDTH': 1.0 / width,
16947 'CUBEUV_TEXEL_HEIGHT': 1.0 / height,
16948 'CUBEUV_MAX_MIP': `
${lodMax}.0`,
16952 'envMap': { value:
null },
16953 'samples': { value: 1 },
16954 'weights': { value: weights },
16955 'latitudinal': { value:
false },
16956 'dTheta': { value: 0 },
16957 'mipInt': { value: 0 },
16958 'poleAxis': { value: poleAxis }
16961 vertexShader: _getCommonVertexShader(),
16965 precision mediump float;
16966 precision mediump int;
16968 varying vec3 vOutputDirection;
16970 uniform sampler2D envMap;
16971 uniform
int samples;
16972 uniform
float weights[
n ];
16973 uniform
bool latitudinal;
16974 uniform
float dTheta;
16975 uniform
float mipInt;
16976 uniform vec3 poleAxis;
16978 #define ENVMAP_TYPE_CUBE_UV
16979 #include <cube_uv_reflection_fragment>
16981 vec3 getSample(
float theta, vec3 axis ) {
16983 float cosTheta = cos( theta );
16985 vec3 sampleDirection = vOutputDirection * cosTheta
16986 + cross( axis, vOutputDirection ) * sin( theta )
16987 + axis * dot( axis, vOutputDirection ) * ( 1.0 - cosTheta );
16989 return bilinearCubeUV( envMap, sampleDirection, mipInt );
16995 vec3 axis = latitudinal ? poleAxis : cross( poleAxis, vOutputDirection );
16997 if ( all( equal( axis, vec3( 0.0 ) ) ) ) {
16999 axis = vec3( vOutputDirection.z, 0.0, - vOutputDirection.x );
17003 axis = normalize( axis );
17005 gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
17006 gl_FragColor.rgb += weights[ 0 ] * getSample( 0.0, axis );
17008 for (
int i = 1;
i <
n;
i++ ) {
17010 if (
i >= samples ) {
17016 float theta = dTheta * float(
i );
17017 gl_FragColor.rgb += weights[
i ] * getSample( -1.0 * theta, axis );
17018 gl_FragColor.rgb += weights[
i ] * getSample( theta, axis );
17031 return shaderMaterial;
17035 function _getEquirectMaterial() {
17039 name:
'EquirectangularToCubeUV',
17042 'envMap': { value:
null }
17045 vertexShader: _getCommonVertexShader(),
17049 precision mediump float;
17050 precision mediump int;
17052 varying vec3 vOutputDirection;
17054 uniform sampler2D envMap;
17060 vec3 outputDirection = normalize( vOutputDirection );
17061 vec2 uv = equirectUv( outputDirection );
17063 gl_FragColor = vec4( texture2D ( envMap, uv ).rgb, 1.0 );
17076 function _getCubemapMaterial() {
17080 name:
'CubemapToCubeUV',
17083 'envMap': { value:
null },
17084 'flipEnvMap': { value: - 1 }
17087 vertexShader: _getCommonVertexShader(),
17091 precision mediump float;
17092 precision mediump int;
17094 uniform
float flipEnvMap;
17096 varying vec3 vOutputDirection;
17098 uniform samplerCube envMap;
17102 gl_FragColor = textureCube( envMap, vec3( flipEnvMap * vOutputDirection.x, vOutputDirection.yz ) );
17115 function _getCommonVertexShader() {
17119 precision mediump float;
17120 precision mediump int;
17122 attribute
float faceIndex;
17124 varying vec3 vOutputDirection;
17127 vec3 getDirection( vec2 uv,
float face ) {
17129 uv = 2.0 * uv - 1.0;
17131 vec3 direction = vec3( uv, 1.0 );
17133 if ( face == 0.0 ) {
17135 direction = direction.zyx;
17137 }
else if ( face == 1.0 ) {
17139 direction = direction.xzy;
17140 direction.xz *= -1.0;
17142 }
else if ( face == 2.0 ) {
17144 direction.x *= -1.0;
17146 }
else if ( face == 3.0 ) {
17148 direction = direction.zyx;
17149 direction.xz *= -1.0;
17151 }
else if ( face == 4.0 ) {
17153 direction = direction.xzy;
17154 direction.xy *= -1.0;
17156 }
else if ( face == 5.0 ) {
17158 direction.z *= -1.0;
17168 vOutputDirection = getDirection( uv, faceIndex );
17169 gl_Position = vec4(
position, 1.0 );
17176 function WebGLCubeUVMaps( renderer ) {
17178 let cubeUVmaps =
new WeakMap();
17180 let pmremGenerator =
null;
17182 function get( texture ) {
17184 if ( texture && texture.isTexture ) {
17186 const mapping = texture.mapping;
17188 const isEquirectMap = ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping );
17193 if ( isEquirectMap || isCubeMap ) {
17195 if ( texture.isRenderTargetTexture && texture.needsPMREMUpdate ===
true ) {
17197 texture.needsPMREMUpdate =
false;
17199 let renderTarget = cubeUVmaps.get( texture );
17201 if ( pmremGenerator ===
null ) pmremGenerator =
new PMREMGenerator( renderer );
17203 renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture, renderTarget ) : pmremGenerator.fromCubemap( texture, renderTarget );
17204 cubeUVmaps.set( texture, renderTarget );
17206 return renderTarget.texture;
17210 if ( cubeUVmaps.has( texture ) ) {
17212 return cubeUVmaps.get( texture ).texture;
17216 const image = texture.image;
17218 if ( ( isEquirectMap && image && image.height > 0 ) || ( isCubeMap && image && isCubeTextureComplete( image ) ) ) {
17220 if ( pmremGenerator ===
null ) pmremGenerator =
new PMREMGenerator( renderer );
17222 const renderTarget = isEquirectMap ? pmremGenerator.fromEquirectangular( texture ) : pmremGenerator.fromCubemap( texture );
17223 cubeUVmaps.set( texture, renderTarget );
17225 texture.addEventListener(
'dispose', onTextureDispose );
17227 return renderTarget.texture;
17249 function isCubeTextureComplete( image ) {
17254 for ( let
i = 0;
i < length;
i ++ ) {
17260 return count === length;
17265 function onTextureDispose( event ) {
17267 const texture =
event.target;
17269 texture.removeEventListener(
'dispose', onTextureDispose );
17271 const cubemapUV = cubeUVmaps.get( texture );
17275 cubeUVmaps.delete( texture );
17276 cubemapUV.dispose();
17284 cubeUVmaps =
new WeakMap();
17286 if ( pmremGenerator !==
null ) {
17288 pmremGenerator.dispose();
17289 pmremGenerator =
null;
17302 function WebGLExtensions( gl ) {
17304 const extensions = {};
17306 function getExtension( name ) {
17308 if ( extensions[ name ] !==
undefined ) {
17310 return extensions[ name ];
17318 case 'WEBGL_depth_texture':
17319 extension = gl.getExtension(
'WEBGL_depth_texture' ) || gl.getExtension(
'MOZ_WEBGL_depth_texture' ) || gl.getExtension(
'WEBKIT_WEBGL_depth_texture' );
17322 case 'EXT_texture_filter_anisotropic':
17323 extension = gl.getExtension(
'EXT_texture_filter_anisotropic' ) || gl.getExtension(
'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension(
'WEBKIT_EXT_texture_filter_anisotropic' );
17326 case 'WEBGL_compressed_texture_s3tc':
17327 extension = gl.getExtension(
'WEBGL_compressed_texture_s3tc' ) || gl.getExtension(
'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension(
'WEBKIT_WEBGL_compressed_texture_s3tc' );
17330 case 'WEBGL_compressed_texture_pvrtc':
17331 extension = gl.getExtension(
'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension(
'WEBKIT_WEBGL_compressed_texture_pvrtc' );
17335 extension = gl.getExtension( name );
17339 extensions[ name ] = extension;
17347 has:
function ( name ) {
17349 return getExtension( name ) !==
null;
17353 init:
function ( capabilities ) {
17355 if ( capabilities.isWebGL2 ) {
17357 getExtension(
'EXT_color_buffer_float' );
17358 getExtension(
'WEBGL_clip_cull_distance' );
17362 getExtension(
'WEBGL_depth_texture' );
17363 getExtension(
'OES_texture_float' );
17364 getExtension(
'OES_texture_half_float' );
17365 getExtension(
'OES_texture_half_float_linear' );
17366 getExtension(
'OES_standard_derivatives' );
17367 getExtension(
'OES_element_index_uint' );
17368 getExtension(
'OES_vertex_array_object' );
17369 getExtension(
'ANGLE_instanced_arrays' );
17373 getExtension(
'OES_texture_float_linear' );
17374 getExtension(
'EXT_color_buffer_half_float' );
17375 getExtension(
'WEBGL_multisampled_render_to_texture' );
17379 get:
function ( name ) {
17381 const extension = getExtension( name );
17383 if ( extension ===
null ) {
17385 console.warn(
'THREE.WebGLRenderer: ' + name +
' extension not supported.' );
17397 function WebGLGeometries( gl, attributes, info, bindingStates ) {
17399 const geometries = {};
17400 const wireframeAttributes =
new WeakMap();
17402 function onGeometryDispose( event ) {
17404 const geometry =
event.target;
17406 if ( geometry.index !==
null ) {
17408 attributes.remove( geometry.index );
17412 for (
const name in geometry.attributes ) {
17414 attributes.remove( geometry.attributes[ name ] );
17418 for (
const name in geometry.morphAttributes ) {
17420 const array = geometry.morphAttributes[ name ];
17422 for ( let
i = 0,
l = array.length;
i <
l;
i ++ ) {
17424 attributes.remove( array[
i ] );
17430 geometry.removeEventListener(
'dispose', onGeometryDispose );
17432 delete geometries[ geometry.id ];
17434 const attribute = wireframeAttributes.get( geometry );
17438 attributes.remove( attribute );
17439 wireframeAttributes.delete( geometry );
17443 bindingStates.releaseStatesOfGeometry( geometry );
17445 if ( geometry.isInstancedBufferGeometry ===
true ) {
17447 delete geometry._maxInstanceCount;
17453 info.memory.geometries --;
17457 function get(
object, geometry ) {
17459 if ( geometries[ geometry.id ] ===
true )
return geometry;
17461 geometry.addEventListener(
'dispose', onGeometryDispose );
17463 geometries[ geometry.id ] =
true;
17465 info.memory.geometries ++;
17471 function update( geometry ) {
17473 const geometryAttributes = geometry.attributes;
17477 for (
const name in geometryAttributes ) {
17479 attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
17485 const morphAttributes = geometry.morphAttributes;
17487 for (
const name in morphAttributes ) {
17489 const array = morphAttributes[ name ];
17491 for ( let
i = 0,
l = array.length;
i <
l;
i ++ ) {
17493 attributes.update( array[
i ], gl.ARRAY_BUFFER );
17501 function updateWireframeAttribute( geometry ) {
17503 const indices = [];
17505 const geometryIndex = geometry.index;
17506 const geometryPosition = geometry.attributes.position;
17509 if ( geometryIndex !==
null ) {
17511 const array = geometryIndex.array;
17512 version = geometryIndex.version;
17514 for ( let
i = 0,
l = array.length;
i <
l;
i += 3 ) {
17516 const a = array[
i + 0 ];
17517 const b = array[
i + 1 ];
17518 const c = array[
i + 2 ];
17520 indices.push(
a,
b,
b,
c,
c,
a );
17524 }
else if ( geometryPosition !==
undefined ) {
17526 const array = geometryPosition.array;
17527 version = geometryPosition.version;
17529 for ( let
i = 0,
l = ( array.length / 3 ) - 1;
i <
l;
i += 3 ) {
17535 indices.push(
a,
b,
b,
c,
c,
a );
17545 const attribute =
new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
17552 const previousAttribute = wireframeAttributes.get( geometry );
17554 if ( previousAttribute ) attributes.remove( previousAttribute );
17558 wireframeAttributes.set( geometry, attribute );
17562 function getWireframeAttribute( geometry ) {
17564 const currentAttribute = wireframeAttributes.get( geometry );
17566 if ( currentAttribute ) {
17568 const geometryIndex = geometry.index;
17570 if ( geometryIndex !==
null ) {
17574 if ( currentAttribute.version < geometryIndex.version ) {
17576 updateWireframeAttribute( geometry );
17584 updateWireframeAttribute( geometry );
17588 return wireframeAttributes.get( geometry );
17597 getWireframeAttribute: getWireframeAttribute
17603 function WebGLIndexedBufferRenderer( gl, extensions, info, capabilities ) {
17605 const isWebGL2 = capabilities.isWebGL2;
17609 function setMode( value ) {
17615 let type, bytesPerElement;
17617 function setIndex( value ) {
17620 bytesPerElement = value.bytesPerElement;
17624 function render( start, count ) {
17626 gl.drawElements( mode, count, type, start * bytesPerElement );
17628 info.update( count, mode, 1 );
17632 function renderInstances( start, count, primcount ) {
17634 if ( primcount === 0 )
return;
17636 let extension, methodName;
17641 methodName =
'drawElementsInstanced';
17645 extension = extensions.get(
'ANGLE_instanced_arrays' );
17646 methodName =
'drawElementsInstancedANGLE';
17648 if ( extension ===
null ) {
17650 console.error(
'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' );
17657 extension[ methodName ]( mode, count, type, start * bytesPerElement, primcount );
17659 info.update( count, mode, primcount );
17663 function renderMultiDraw( starts, counts, drawCount ) {
17665 if ( drawCount === 0 )
return;
17667 const extension = extensions.get(
'WEBGL_multi_draw' );
17668 if ( extension ===
null ) {
17670 for ( let
i = 0;
i < drawCount;
i ++ ) {
17672 this.render( starts[
i ] / bytesPerElement, counts[
i ] );
17678 extension.multiDrawElementsWEBGL( mode, counts, 0, type, starts, 0, drawCount );
17680 let elementCount = 0;
17681 for ( let
i = 0;
i < drawCount;
i ++ ) {
17683 elementCount += counts[
i ];
17687 info.update( elementCount, mode, 1 );
17695 this.setMode = setMode;
17696 this.setIndex = setIndex;
17697 this.render = render;
17698 this.renderInstances = renderInstances;
17699 this.renderMultiDraw = renderMultiDraw;
17703 function WebGLInfo( gl ) {
17718 function update( count, mode, instanceCount ) {
17725 render.triangles += instanceCount * ( count / 3 );
17729 render.lines += instanceCount * ( count / 2 );
17732 case gl.LINE_STRIP:
17733 render.lines += instanceCount * ( count - 1 );
17737 render.lines += instanceCount * count;
17741 render.points += instanceCount * count;
17745 console.error(
'THREE.WebGLInfo: Unknown draw mode:', mode );
17755 render.triangles = 0;
17772 function numericalSort(
a,
b ) {
17774 return a[ 0 ] -
b[ 0 ];
17778 function absNumericalSort(
a,
b ) {
17780 return Math.abs(
b[ 1 ] ) -
Math.abs(
a[ 1 ] );
17784 function WebGLMorphtargets( gl, capabilities, textures ) {
17786 const influencesList = {};
17788 const morphTextures =
new WeakMap();
17791 const workInfluences = [];
17793 for ( let
i = 0;
i < 8;
i ++ ) {
17795 workInfluences[
i ] = [
i, 0 ];
17799 function update(
object, geometry, program ) {
17801 const objectInfluences =
object.morphTargetInfluences;
17803 if ( capabilities.isWebGL2 ===
true ) {
17808 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
17809 const morphTargetsCount = ( morphAttribute !==
undefined ) ? morphAttribute.length : 0;
17811 let entry = morphTextures.get( geometry );
17813 if ( entry ===
undefined || entry.count !== morphTargetsCount ) {
17815 if ( entry !==
undefined ) entry.texture.dispose();
17817 const hasMorphPosition = geometry.morphAttributes.position !==
undefined;
17818 const hasMorphNormals = geometry.morphAttributes.normal !==
undefined;
17819 const hasMorphColors = geometry.morphAttributes.color !==
undefined;
17821 const morphTargets = geometry.morphAttributes.position || [];
17822 const morphNormals = geometry.morphAttributes.normal || [];
17823 const morphColors = geometry.morphAttributes.color || [];
17825 let vertexDataCount = 0;
17827 if ( hasMorphPosition ===
true ) vertexDataCount = 1;
17828 if ( hasMorphNormals ===
true ) vertexDataCount = 2;
17829 if ( hasMorphColors ===
true ) vertexDataCount = 3;
17831 let width = geometry.attributes.position.count * vertexDataCount;
17834 if ( width > capabilities.maxTextureSize ) {
17836 height =
Math.ceil( width / capabilities.maxTextureSize );
17837 width = capabilities.maxTextureSize;
17841 const buffer =
new Float32Array( width * height * 4 * morphTargetsCount );
17843 const texture =
new DataArrayTexture( buffer, width, height, morphTargetsCount );
17845 texture.needsUpdate =
true;
17849 const vertexDataStride = vertexDataCount * 4;
17851 for ( let
i = 0;
i < morphTargetsCount;
i ++ ) {
17853 const morphTarget = morphTargets[
i ];
17854 const morphNormal = morphNormals[
i ];
17855 const morphColor = morphColors[
i ];
17857 const offset = width * height * 4 *
i;
17859 for ( let
j = 0;
j < morphTarget.count;
j ++ ) {
17861 const stride =
j * vertexDataStride;
17863 if ( hasMorphPosition ===
true ) {
17865 morph.fromBufferAttribute( morphTarget,
j );
17867 buffer[ offset + stride + 0 ] = morph.x;
17868 buffer[ offset + stride + 1 ] = morph.y;
17869 buffer[ offset + stride + 2 ] = morph.z;
17870 buffer[ offset + stride + 3 ] = 0;
17874 if ( hasMorphNormals ===
true ) {
17876 morph.fromBufferAttribute( morphNormal,
j );
17878 buffer[ offset + stride + 4 ] = morph.x;
17879 buffer[ offset + stride + 5 ] = morph.y;
17880 buffer[ offset + stride + 6 ] = morph.z;
17881 buffer[ offset + stride + 7 ] = 0;
17885 if ( hasMorphColors ===
true ) {
17887 morph.fromBufferAttribute( morphColor,
j );
17889 buffer[ offset + stride + 8 ] = morph.x;
17890 buffer[ offset + stride + 9 ] = morph.y;
17891 buffer[ offset + stride + 10 ] = morph.z;
17892 buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? morph.w : 1;
17901 count: morphTargetsCount,
17903 size:
new Vector2( width, height )
17906 morphTextures.set( geometry, entry );
17908 function disposeTexture() {
17912 morphTextures.delete( geometry );
17914 geometry.removeEventListener(
'dispose', disposeTexture );
17918 geometry.addEventListener(
'dispose', disposeTexture );
17924 let morphInfluencesSum = 0;
17926 for ( let
i = 0;
i < objectInfluences.length;
i ++ ) {
17928 morphInfluencesSum += objectInfluences[
i ];
17932 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
17934 program.getUniforms().setValue( gl,
'morphTargetBaseInfluence', morphBaseInfluence );
17935 program.getUniforms().setValue( gl,
'morphTargetInfluences', objectInfluences );
17937 program.getUniforms().setValue( gl,
'morphTargetsTexture', entry.texture, textures );
17938 program.getUniforms().setValue( gl,
'morphTargetsTextureSize', entry.size );
17946 const length = objectInfluences ===
undefined ? 0 : objectInfluences.length;
17948 let influences = influencesList[ geometry.id ];
17950 if ( influences ===
undefined || influences.length !== length ) {
17956 for ( let
i = 0;
i < length;
i ++ ) {
17958 influences[
i ] = [
i, 0 ];
17962 influencesList[ geometry.id ] = influences;
17968 for ( let
i = 0;
i < length;
i ++ ) {
17970 const influence = influences[
i ];
17972 influence[ 0 ] =
i;
17973 influence[ 1 ] = objectInfluences[
i ];
17977 influences.sort( absNumericalSort );
17979 for ( let
i = 0;
i < 8;
i ++ ) {
17981 if (
i < length && influences[
i ][ 1 ] ) {
17983 workInfluences[
i ][ 0 ] = influences[
i ][ 0 ];
17984 workInfluences[
i ][ 1 ] = influences[
i ][ 1 ];
17988 workInfluences[
i ][ 0 ] =
Number.MAX_SAFE_INTEGER;
17989 workInfluences[
i ][ 1 ] = 0;
17995 workInfluences.sort( numericalSort );
17997 const morphTargets = geometry.morphAttributes.position;
17998 const morphNormals = geometry.morphAttributes.normal;
18000 let morphInfluencesSum = 0;
18002 for ( let
i = 0;
i < 8;
i ++ ) {
18004 const influence = workInfluences[
i ];
18005 const index = influence[ 0 ];
18006 const value = influence[ 1 ];
18008 if ( index !==
Number.MAX_SAFE_INTEGER && value ) {
18010 if ( morphTargets && geometry.getAttribute(
'morphTarget' +
i ) !== morphTargets[ index ] ) {
18012 geometry.setAttribute(
'morphTarget' +
i, morphTargets[ index ] );
18016 if ( morphNormals && geometry.getAttribute(
'morphNormal' +
i ) !== morphNormals[ index ] ) {
18018 geometry.setAttribute(
'morphNormal' +
i, morphNormals[ index ] );
18022 morphInfluences[
i ] = value;
18023 morphInfluencesSum += value;
18027 if ( morphTargets && geometry.hasAttribute(
'morphTarget' +
i ) ===
true ) {
18029 geometry.deleteAttribute(
'morphTarget' +
i );
18033 if ( morphNormals && geometry.hasAttribute(
'morphNormal' +
i ) ===
true ) {
18035 geometry.deleteAttribute(
'morphNormal' +
i );
18039 morphInfluences[
i ] = 0;
18048 const morphBaseInfluence = geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum;
18050 program.getUniforms().setValue( gl,
'morphTargetBaseInfluence', morphBaseInfluence );
18051 program.getUniforms().setValue( gl,
'morphTargetInfluences', morphInfluences );
18065 function WebGLObjects( gl, geometries, attributes, info ) {
18067 let updateMap =
new WeakMap();
18069 function update(
object ) {
18071 const frame = info.render.frame;
18073 const geometry =
object.geometry;
18074 const buffergeometry = geometries.get(
object, geometry );
18078 if ( updateMap.get( buffergeometry ) !== frame ) {
18080 geometries.update( buffergeometry );
18082 updateMap.set( buffergeometry, frame );
18086 if (
object.isInstancedMesh ) {
18088 if (
object.hasEventListener(
'dispose', onInstancedMeshDispose ) ===
false ) {
18090 object.addEventListener(
'dispose', onInstancedMeshDispose );
18094 if ( updateMap.get(
object ) !== frame ) {
18096 attributes.update(
object.instanceMatrix, gl.ARRAY_BUFFER );
18098 if (
object.instanceColor !==
null ) {
18100 attributes.update(
object.instanceColor, gl.ARRAY_BUFFER );
18104 updateMap.set(
object, frame );
18110 if (
object.isSkinnedMesh ) {
18112 const skeleton =
object.skeleton;
18114 if ( updateMap.get( skeleton ) !== frame ) {
18118 updateMap.set( skeleton, frame );
18124 return buffergeometry;
18130 updateMap =
new WeakMap();
18134 function onInstancedMeshDispose( event ) {
18136 const instancedMesh =
event.target;
18138 instancedMesh.removeEventListener(
'dispose', onInstancedMeshDispose );
18140 attributes.remove( instancedMesh.instanceMatrix );
18142 if ( instancedMesh.instanceColor !==
null ) attributes.remove( instancedMesh.instanceColor );
18155 class DepthTexture
extends Texture {
18157 constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) {
18159 format = format !==
undefined ? format : DepthFormat;
18161 if ( format !== DepthFormat && format !== DepthStencilFormat ) {
18163 throw new Error(
'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' );
18168 if ( type ===
undefined && format === DepthStencilFormat ) type = UnsignedInt248Type;
18170 super(
null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
18172 this.isDepthTexture =
true;
18174 this.image = { width: width, height: height };
18179 this.flipY =
false;
18180 this.generateMipmaps =
false;
18182 this.compareFunction =
null;
18189 super.copy( source );
18191 this.compareFunction = source.compareFunction;
18199 const data = super.toJSON( meta );
18201 if ( this.compareFunction !==
null ) data.compareFunction = this.compareFunction;
18253 const emptyTexture =
new Texture();
18255 const emptyShadowTexture =
new DepthTexture( 1, 1 );
18256 emptyShadowTexture.compareFunction = LessEqualCompare;
18258 const emptyArrayTexture =
new DataArrayTexture();
18259 const empty3dTexture =
new Data3DTexture();
18266 const arrayCacheF32 = [];
18267 const arrayCacheI32 = [];
18277 function flatten( array, nBlocks, blockSize ) {
18279 const firstElem = array[ 0 ];
18281 if ( firstElem <= 0 || firstElem > 0 )
return array;
18285 const n = nBlocks * blockSize;
18286 let
r = arrayCacheF32[
n ];
18291 arrayCacheF32[
n ] =
r;
18295 if ( nBlocks !== 0 ) {
18297 firstElem.toArray(
r, 0 );
18299 for ( let
i = 1, offset = 0;
i !== nBlocks; ++
i ) {
18301 offset += blockSize;
18302 array[
i ].toArray(
r, offset );
18312 function arraysEqual(
a,
b ) {
18314 if (
a.length !==
b.length )
return false;
18316 for ( let
i = 0,
l =
a.length;
i <
l;
i ++ ) {
18318 if (
a[
i ] !==
b[
i ] )
return false;
18326 function copyArray(
a,
b ) {
18328 for ( let
i = 0,
l =
b.length;
i <
l;
i ++ ) {
18338 function allocTexUnits( textures,
n ) {
18340 let
r = arrayCacheI32[
n ];
18345 arrayCacheI32[
n ] =
r;
18349 for ( let
i = 0;
i !==
n; ++
i ) {
18351 r[
i ] = textures.allocateTextureUnit();
18366 function setValueV1f( gl,
v ) {
18368 const cache = this.cache;
18370 if (
cache[ 0 ] ===
v )
return;
18372 gl.uniform1f( this.addr,
v );
18380 function setValueV2f( gl,
v ) {
18382 const cache = this.cache;
18388 gl.uniform2f( this.addr,
v.x,
v.y );
18397 if ( arraysEqual(
cache,
v ) )
return;
18399 gl.uniform2fv( this.addr,
v );
18407 function setValueV3f( gl,
v ) {
18409 const cache = this.cache;
18415 gl.uniform3f( this.addr,
v.x,
v.y,
v.z );
18427 gl.uniform3f( this.addr,
v.r,
v.g,
v.b );
18437 if ( arraysEqual(
cache,
v ) )
return;
18439 gl.uniform3fv( this.addr,
v );
18447 function setValueV4f( gl,
v ) {
18449 const cache = this.cache;
18455 gl.uniform4f( this.addr,
v.x,
v.y,
v.z,
v.w );
18466 if ( arraysEqual(
cache,
v ) )
return;
18468 gl.uniform4fv( this.addr,
v );
18478 function setValueM2( gl,
v ) {
18480 const cache = this.cache;
18481 const elements =
v.elements;
18485 if ( arraysEqual(
cache,
v ) )
return;
18487 gl.uniformMatrix2fv( this.addr,
false,
v );
18493 if ( arraysEqual(
cache, elements ) )
return;
18495 mat2array.set( elements );
18497 gl.uniformMatrix2fv( this.addr,
false, mat2array );
18499 copyArray(
cache, elements );
18505 function setValueM3( gl,
v ) {
18507 const cache = this.cache;
18508 const elements =
v.elements;
18512 if ( arraysEqual(
cache,
v ) )
return;
18514 gl.uniformMatrix3fv( this.addr,
false,
v );
18520 if ( arraysEqual(
cache, elements ) )
return;
18522 mat3array.set( elements );
18524 gl.uniformMatrix3fv( this.addr,
false, mat3array );
18526 copyArray(
cache, elements );
18532 function setValueM4( gl,
v ) {
18534 const cache = this.cache;
18535 const elements =
v.elements;
18539 if ( arraysEqual(
cache,
v ) )
return;
18541 gl.uniformMatrix4fv( this.addr,
false,
v );
18547 if ( arraysEqual(
cache, elements ) )
return;
18549 mat4array.set( elements );
18551 gl.uniformMatrix4fv( this.addr,
false, mat4array );
18553 copyArray(
cache, elements );
18561 function setValueV1i( gl,
v ) {
18563 const cache = this.cache;
18565 if (
cache[ 0 ] ===
v )
return;
18567 gl.uniform1i( this.addr,
v );
18575 function setValueV2i( gl,
v ) {
18577 const cache = this.cache;
18583 gl.uniform2i( this.addr,
v.x,
v.y );
18592 if ( arraysEqual(
cache,
v ) )
return;
18594 gl.uniform2iv( this.addr,
v );
18602 function setValueV3i( gl,
v ) {
18604 const cache = this.cache;
18610 gl.uniform3i( this.addr,
v.x,
v.y,
v.z );
18620 if ( arraysEqual(
cache,
v ) )
return;
18622 gl.uniform3iv( this.addr,
v );
18630 function setValueV4i( gl,
v ) {
18632 const cache = this.cache;
18638 gl.uniform4i( this.addr,
v.x,
v.y,
v.z,
v.w );
18649 if ( arraysEqual(
cache,
v ) )
return;
18651 gl.uniform4iv( this.addr,
v );
18661 function setValueV1ui( gl,
v ) {
18663 const cache = this.cache;
18665 if (
cache[ 0 ] ===
v )
return;
18667 gl.uniform1ui( this.addr,
v );
18675 function setValueV2ui( gl,
v ) {
18677 const cache = this.cache;
18683 gl.uniform2ui( this.addr,
v.x,
v.y );
18692 if ( arraysEqual(
cache,
v ) )
return;
18694 gl.uniform2uiv( this.addr,
v );
18702 function setValueV3ui( gl,
v ) {
18704 const cache = this.cache;
18710 gl.uniform3ui( this.addr,
v.x,
v.y,
v.z );
18720 if ( arraysEqual(
cache,
v ) )
return;
18722 gl.uniform3uiv( this.addr,
v );
18730 function setValueV4ui( gl,
v ) {
18732 const cache = this.cache;
18738 gl.uniform4ui( this.addr,
v.x,
v.y,
v.z,
v.w );
18749 if ( arraysEqual(
cache,
v ) )
return;
18751 gl.uniform4uiv( this.addr,
v );
18762 function setValueT1( gl,
v, textures ) {
18764 const cache = this.cache;
18765 const unit = textures.allocateTextureUnit();
18767 if (
cache[ 0 ] !== unit ) {
18769 gl.uniform1i( this.addr, unit );
18774 const emptyTexture2D = ( this.type === gl.SAMPLER_2D_SHADOW ) ? emptyShadowTexture : emptyTexture;
18776 textures.setTexture2D(
v || emptyTexture2D, unit );
18780 function setValueT3D1( gl,
v, textures ) {
18782 const cache = this.cache;
18783 const unit = textures.allocateTextureUnit();
18785 if (
cache[ 0 ] !== unit ) {
18787 gl.uniform1i( this.addr, unit );
18792 textures.setTexture3D(
v || empty3dTexture, unit );
18796 function setValueT6( gl,
v, textures ) {
18798 const cache = this.cache;
18799 const unit = textures.allocateTextureUnit();
18801 if (
cache[ 0 ] !== unit ) {
18803 gl.uniform1i( this.addr, unit );
18808 textures.setTextureCube(
v || emptyCubeTexture, unit );
18812 function setValueT2DArray1( gl,
v, textures ) {
18814 const cache = this.cache;
18815 const unit = textures.allocateTextureUnit();
18817 if (
cache[ 0 ] !== unit ) {
18819 gl.uniform1i( this.addr, unit );
18824 textures.setTexture2DArray(
v || emptyArrayTexture, unit );
18830 function getSingularSetter( type ) {
18834 case 0x1406:
return setValueV1f;
18835 case 0x8b50:
return setValueV2f;
18836 case 0x8b51:
return setValueV3f;
18837 case 0x8b52:
return setValueV4f;
18839 case 0x8b5a:
return setValueM2;
18840 case 0x8b5b:
return setValueM3;
18841 case 0x8b5c:
return setValueM4;
18843 case 0x1404:
case 0x8b56:
return setValueV1i;
18844 case 0x8b53:
case 0x8b57:
return setValueV2i;
18845 case 0x8b54:
case 0x8b58:
return setValueV3i;
18846 case 0x8b55:
case 0x8b59:
return setValueV4i;
18848 case 0x1405:
return setValueV1ui;
18849 case 0x8dc6:
return setValueV2ui;
18850 case 0x8dc7:
return setValueV3ui;
18851 case 0x8dc8:
return setValueV4ui;
18863 return setValueT3D1;
18875 return setValueT2DArray1;
18884 function setValueV1fArray( gl,
v ) {
18886 gl.uniform1fv( this.addr,
v );
18892 function setValueV2fArray( gl,
v ) {
18894 const data = flatten(
v, this.size, 2 );
18896 gl.uniform2fv( this.addr, data );
18900 function setValueV3fArray( gl,
v ) {
18902 const data = flatten(
v, this.size, 3 );
18904 gl.uniform3fv( this.addr, data );
18908 function setValueV4fArray( gl,
v ) {
18910 const data = flatten(
v, this.size, 4 );
18912 gl.uniform4fv( this.addr, data );
18918 function setValueM2Array( gl,
v ) {
18920 const data = flatten(
v, this.size, 4 );
18922 gl.uniformMatrix2fv( this.addr,
false, data );
18926 function setValueM3Array( gl,
v ) {
18928 const data = flatten(
v, this.size, 9 );
18930 gl.uniformMatrix3fv( this.addr,
false, data );
18934 function setValueM4Array( gl,
v ) {
18936 const data = flatten(
v, this.size, 16 );
18938 gl.uniformMatrix4fv( this.addr,
false, data );
18944 function setValueV1iArray( gl,
v ) {
18946 gl.uniform1iv( this.addr,
v );
18952 function setValueV2iArray( gl,
v ) {
18954 gl.uniform2iv( this.addr,
v );
18958 function setValueV3iArray( gl,
v ) {
18960 gl.uniform3iv( this.addr,
v );
18964 function setValueV4iArray( gl,
v ) {
18966 gl.uniform4iv( this.addr,
v );
18972 function setValueV1uiArray( gl,
v ) {
18974 gl.uniform1uiv( this.addr,
v );
18980 function setValueV2uiArray( gl,
v ) {
18982 gl.uniform2uiv( this.addr,
v );
18986 function setValueV3uiArray( gl,
v ) {
18988 gl.uniform3uiv( this.addr,
v );
18992 function setValueV4uiArray( gl,
v ) {
18994 gl.uniform4uiv( this.addr,
v );
19001 function setValueT1Array( gl,
v, textures ) {
19003 const cache = this.cache;
19005 const n =
v.length;
19007 const units = allocTexUnits( textures,
n );
19009 if ( ! arraysEqual(
cache, units ) ) {
19011 gl.uniform1iv( this.addr, units );
19013 copyArray(
cache, units );
19017 for ( let
i = 0;
i !==
n; ++
i ) {
19019 textures.setTexture2D(
v[
i ] || emptyTexture, units[
i ] );
19025 function setValueT3DArray( gl,
v, textures ) {
19027 const cache = this.cache;
19029 const n =
v.length;
19031 const units = allocTexUnits( textures,
n );
19033 if ( ! arraysEqual(
cache, units ) ) {
19035 gl.uniform1iv( this.addr, units );
19037 copyArray(
cache, units );
19041 for ( let
i = 0;
i !==
n; ++
i ) {
19043 textures.setTexture3D(
v[
i ] || empty3dTexture, units[
i ] );
19049 function setValueT6Array( gl,
v, textures ) {
19051 const cache = this.cache;
19053 const n =
v.length;
19055 const units = allocTexUnits( textures,
n );
19057 if ( ! arraysEqual(
cache, units ) ) {
19059 gl.uniform1iv( this.addr, units );
19061 copyArray(
cache, units );
19065 for ( let
i = 0;
i !==
n; ++
i ) {
19067 textures.setTextureCube(
v[
i ] || emptyCubeTexture, units[
i ] );
19073 function setValueT2DArrayArray( gl,
v, textures ) {
19075 const cache = this.cache;
19077 const n =
v.length;
19079 const units = allocTexUnits( textures,
n );
19081 if ( ! arraysEqual(
cache, units ) ) {
19083 gl.uniform1iv( this.addr, units );
19085 copyArray(
cache, units );
19089 for ( let
i = 0;
i !==
n; ++
i ) {
19091 textures.setTexture2DArray(
v[
i ] || emptyArrayTexture, units[
i ] );
19100 function getPureArraySetter( type ) {
19104 case 0x1406:
return setValueV1fArray;
19105 case 0x8b50:
return setValueV2fArray;
19106 case 0x8b51:
return setValueV3fArray;
19107 case 0x8b52:
return setValueV4fArray;
19109 case 0x8b5a:
return setValueM2Array;
19110 case 0x8b5b:
return setValueM3Array;
19111 case 0x8b5c:
return setValueM4Array;
19113 case 0x1404:
case 0x8b56:
return setValueV1iArray;
19114 case 0x8b53:
case 0x8b57:
return setValueV2iArray;
19115 case 0x8b54:
case 0x8b58:
return setValueV3iArray;
19116 case 0x8b55:
case 0x8b59:
return setValueV4iArray;
19118 case 0x1405:
return setValueV1uiArray;
19119 case 0x8dc6:
return setValueV2uiArray;
19120 case 0x8dc7:
return setValueV3uiArray;
19121 case 0x8dc8:
return setValueV4uiArray;
19128 return setValueT1Array;
19133 return setValueT3DArray;
19139 return setValueT6Array;
19145 return setValueT2DArrayArray;
19153 class SingleUniform {
19155 constructor(
id, activeInfo, addr ) {
19160 this.type = activeInfo.type;
19161 this.setValue = getSingularSetter( activeInfo.type );
19169 class PureArrayUniform {
19171 constructor(
id, activeInfo, addr ) {
19176 this.type = activeInfo.type;
19177 this.size = activeInfo.size;
19178 this.setValue = getPureArraySetter( activeInfo.type );
19186 class StructuredUniform {
19188 constructor(
id ) {
19197 setValue( gl, value, textures ) {
19199 const seq = this.seq;
19201 for ( let
i = 0,
n = seq.length;
i !==
n; ++
i ) {
19203 const u = seq[
i ];
19204 u.setValue( gl, value[
u.id ], textures );
19216 const RePathPart = /(\
w+)(\])?(\[|\.)?/
g;
19227 function addUniform( container, uniformObject ) {
19229 container.seq.push( uniformObject );
19230 container.map[ uniformObject.id ] = uniformObject;
19234 function parseUniform( activeInfo, addr, container ) {
19236 const path = activeInfo.name,
19237 pathLength = path.length;
19240 RePathPart.lastIndex = 0;
19244 const match = RePathPart.exec( path ),
19245 matchEnd = RePathPart.lastIndex;
19247 let
id = match[ 1 ];
19248 const idIsIndex = match[ 2 ] ===
']',
19249 subscript = match[ 3 ];
19251 if ( idIsIndex )
id =
id | 0;
19253 if ( subscript ===
undefined || subscript ===
'[' && matchEnd + 2 === pathLength ) {
19257 addUniform( container, subscript ===
undefined ?
19258 new SingleUniform(
id, activeInfo, addr ) :
19259 new PureArrayUniform(
id, activeInfo, addr ) );
19267 const map = container.map;
19268 let next = map[ id ];
19272 next =
new StructuredUniform(
id );
19273 addUniform( container, next );
19287 class WebGLUniforms {
19289 constructor( gl, program ) {
19294 const n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS );
19296 for ( let
i = 0;
i <
n; ++
i ) {
19298 const info = gl.getActiveUniform( program,
i ),
19299 addr = gl.getUniformLocation( program, info.name );
19301 parseUniform( info, addr,
this );
19307 setValue( gl, name, value, textures ) {
19309 const u = this.map[ name ];
19311 if (
u !==
undefined )
u.setValue( gl, value, textures );
19315 setOptional( gl,
object, name ) {
19317 const v =
object[ name ];
19319 if (
v !==
undefined ) this.setValue( gl, name,
v );
19323 static upload( gl, seq, values, textures ) {
19325 for ( let
i = 0,
n = seq.length;
i !==
n; ++
i ) {
19327 const u = seq[
i ],
19328 v = values[
u.id ];
19330 if (
v.needsUpdate !==
false ) {
19333 u.setValue( gl,
v.value, textures );
19341 static seqWithValue( seq, values ) {
19345 for ( let
i = 0,
n = seq.length;
i !==
n; ++
i ) {
19347 const u = seq[
i ];
19348 if (
u.id in values )
r.push(
u );
19360 const shader = gl.createShader( type );
19362 gl.shaderSource( shader,
string );
19363 gl.compileShader( shader );
19370 const COMPLETION_STATUS_KHR = 0x91B1;
19372 let programIdCount = 0;
19374 function handleSource(
string, errorLine ) {
19376 const lines =
string.split(
'\n' );
19379 const from =
Math.max( errorLine - 6, 0 );
19380 const to =
Math.min( errorLine + 6, lines.length );
19382 for ( let
i = from;
i < to;
i ++ ) {
19384 const line =
i + 1;
19385 lines2.push( `
${line === errorLine ?
'>' :
' '}
${line}:
${lines[
i ]}` );
19389 return lines2.join(
'\n' );
19393 function getEncodingComponents( colorSpace ) {
19395 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
19396 const encodingPrimaries = ColorManagement.getPrimaries( colorSpace );
19400 if ( workingPrimaries === encodingPrimaries ) {
19404 }
else if ( workingPrimaries === P3Primaries && encodingPrimaries === Rec709Primaries ) {
19406 gamutMapping =
'LinearDisplayP3ToLinearSRGB';
19408 }
else if ( workingPrimaries === Rec709Primaries && encodingPrimaries === P3Primaries ) {
19410 gamutMapping =
'LinearSRGBToLinearDisplayP3';
19414 switch ( colorSpace ) {
19416 case LinearSRGBColorSpace:
19417 case LinearDisplayP3ColorSpace:
19418 return [ gamutMapping,
'LinearTransferOETF' ];
19420 case SRGBColorSpace:
19421 case DisplayP3ColorSpace:
19422 return [ gamutMapping,
'sRGBTransferOETF' ];
19425 console.warn(
'THREE.WebGLProgram: Unsupported color space:', colorSpace );
19426 return [ gamutMapping,
'LinearTransferOETF' ];
19432 function getShaderErrors( gl, shader, type ) {
19434 const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS );
19435 const errors = gl.getShaderInfoLog( shader ).trim();
19437 if ( status && errors ===
'' )
return '';
19439 const errorMatches = /ERROR: 0:(\
d+)/.exec( errors );
19440 if ( errorMatches ) {
19445 const errorLine = parseInt( errorMatches[ 1 ] );
19446 return type.toUpperCase() +
'\n\n' + errors +
'\n\n' + handleSource( gl.getShaderSource( shader ), errorLine );
19456 function getTexelEncodingFunction( functionName, colorSpace ) {
19458 const components = getEncodingComponents( colorSpace );
19459 return `vec4
${functionName}( vec4 value ) {
return ${components[ 0 ]}(
${components[ 1 ]}( value ) ); }`;
19463 function getToneMappingFunction( functionName, toneMapping ) {
19465 let toneMappingName;
19467 switch ( toneMapping ) {
19469 case LinearToneMapping:
19470 toneMappingName =
'Linear';
19473 case ReinhardToneMapping:
19474 toneMappingName =
'Reinhard';
19477 case CineonToneMapping:
19478 toneMappingName =
'OptimizedCineon';
19481 case ACESFilmicToneMapping:
19482 toneMappingName =
'ACESFilmic';
19485 case AgXToneMapping:
19486 toneMappingName =
'AgX';
19489 case CustomToneMapping:
19490 toneMappingName =
'Custom';
19494 console.warn(
'THREE.WebGLProgram: Unsupported toneMapping:', toneMapping );
19495 toneMappingName =
'Linear';
19499 return 'vec3 ' + functionName +
'( vec3 color ) { return ' + toneMappingName +
'ToneMapping( color ); }';
19503 function generateExtensions( parameters ) {
19506 ( parameters.extensionDerivatives || !! parameters.envMapCubeUVHeight || parameters.bumpMap || parameters.normalMapTangentSpace || parameters.clearcoatNormalMap || parameters.flatShading || parameters.shaderID ===
'physical' ) ?
'#extension GL_OES_standard_derivatives : enable' :
'',
19507 ( parameters.extensionFragDepth || parameters.logarithmicDepthBuffer ) && parameters.rendererExtensionFragDepth ?
'#extension GL_EXT_frag_depth : enable' :
'',
19508 ( parameters.extensionDrawBuffers && parameters.rendererExtensionDrawBuffers ) ?
'#extension GL_EXT_draw_buffers : require' :
'',
19509 ( parameters.extensionShaderTextureLOD || parameters.envMap || parameters.transmission ) && parameters.rendererExtensionShaderTextureLod ?
'#extension GL_EXT_shader_texture_lod : enable' :
''
19512 return chunks.filter( filterEmptyLine ).join(
'\n' );
19516 function generateVertexExtensions( parameters ) {
19519 parameters.extensionClipCullDistance ?
'#extension GL_ANGLE_clip_cull_distance : require' :
''
19522 return chunks.filter( filterEmptyLine ).join(
'\n' );
19526 function generateDefines( defines ) {
19530 for (
const name in defines ) {
19532 const value = defines[ name ];
19534 if ( value ===
false )
continue;
19536 chunks.push(
'#define ' + name +
' ' + value );
19540 return chunks.join(
'\n' );
19544 function fetchAttributeLocations( gl, program ) {
19546 const attributes = {};
19548 const n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES );
19550 for ( let
i = 0;
i <
n;
i ++ ) {
19552 const info = gl.getActiveAttrib( program,
i );
19553 const name = info.name;
19555 let locationSize = 1;
19556 if ( info.type === gl.FLOAT_MAT2 ) locationSize = 2;
19557 if ( info.type === gl.FLOAT_MAT3 ) locationSize = 3;
19558 if ( info.type === gl.FLOAT_MAT4 ) locationSize = 4;
19562 attributes[ name ] = {
19564 location: gl.getAttribLocation( program, name ),
19565 locationSize: locationSize
19574 function filterEmptyLine(
string ) {
19576 return string !==
'';
19580 function replaceLightNums(
string, parameters ) {
19582 const numSpotLightCoords = parameters.numSpotLightShadows + parameters.numSpotLightMaps - parameters.numSpotLightShadowsWithMaps;
19585 .replace( /NUM_DIR_LIGHTS/
g, parameters.numDirLights )
19586 .replace( /NUM_SPOT_LIGHTS/
g, parameters.numSpotLights )
19587 .replace( /NUM_SPOT_LIGHT_MAPS/
g, parameters.numSpotLightMaps )
19588 .replace( /NUM_SPOT_LIGHT_COORDS/
g, numSpotLightCoords )
19589 .replace( /NUM_RECT_AREA_LIGHTS/
g, parameters.numRectAreaLights )
19590 .replace( /NUM_POINT_LIGHTS/
g, parameters.numPointLights )
19591 .replace( /NUM_HEMI_LIGHTS/
g, parameters.numHemiLights )
19592 .replace( /NUM_DIR_LIGHT_SHADOWS/
g, parameters.numDirLightShadows )
19593 .replace( /NUM_SPOT_LIGHT_SHADOWS_WITH_MAPS/
g, parameters.numSpotLightShadowsWithMaps )
19594 .replace( /NUM_SPOT_LIGHT_SHADOWS/
g, parameters.numSpotLightShadows )
19595 .replace( /NUM_POINT_LIGHT_SHADOWS/
g, parameters.numPointLightShadows );
19599 function replaceClippingPlaneNums(
string, parameters ) {
19602 .replace( /NUM_CLIPPING_PLANES/
g, parameters.numClippingPlanes )
19603 .replace( /UNION_CLIPPING_PLANES/
g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) );
19609 const includePattern = /^[ \
t]*#
include +<([\w\d./]+)>/gm;
19611 function resolveIncludes(
string ) {
19613 return string.replace( includePattern, includeReplacer );
19617 const shaderChunkMap =
new Map( [
19618 [
'encodings_fragment',
'colorspace_fragment' ],
19619 [
'encodings_pars_fragment',
'colorspace_pars_fragment' ],
19620 [
'output_fragment',
'opaque_fragment' ],
19623 function includeReplacer( match,
include ) {
19629 const newInclude = shaderChunkMap.get(
include );
19634 console.warn(
'THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',
include, newInclude );
19638 throw new Error(
'Can not resolve #include <' +
include +
'>' );
19644 return resolveIncludes(
string );
19650 const unrollLoopPattern = /#pragma unroll_loop_start\s+for\s*\(\
s*int\s+i\s*=\
s*(\
d+)\
s*;\
s*i\s*<\
s*(\
d+)\
s*;\
s*i\s*\+\+\
s*\)\
s*{([\s\S]+?)}\
s+#pragma unroll_loop_end/
g;
19652 function unrollLoops(
string ) {
19654 return string.replace( unrollLoopPattern, loopReplacer );
19658 function loopReplacer( match, start, end, snippet ) {
19662 for ( let
i = parseInt( start );
i < parseInt( end );
i ++ ) {
19665 .replace( /\[\
s*
i\
s*\]/
g,
'[ ' +
i +
' ]' )
19666 .replace( /UNROLLED_LOOP_INDEX/
g,
i );
19676 function generatePrecision( parameters ) {
19678 let precisionstring =
'precision ' + parameters.precision +
' float;\nprecision ' + parameters.precision +
' int;';
19680 if ( parameters.precision ===
'highp' ) {
19682 precisionstring +=
'\n#define HIGH_PRECISION';
19684 }
else if ( parameters.precision ===
'mediump' ) {
19686 precisionstring +=
'\n#define MEDIUM_PRECISION';
19688 }
else if ( parameters.precision ===
'lowp' ) {
19690 precisionstring +=
'\n#define LOW_PRECISION';
19694 return precisionstring;
19698 function generateShadowMapTypeDefine( parameters ) {
19700 let shadowMapTypeDefine =
'SHADOWMAP_TYPE_BASIC';
19704 shadowMapTypeDefine =
'SHADOWMAP_TYPE_PCF';
19708 shadowMapTypeDefine =
'SHADOWMAP_TYPE_PCF_SOFT';
19710 }
else if ( parameters.shadowMapType === VSMShadowMap ) {
19712 shadowMapTypeDefine =
'SHADOWMAP_TYPE_VSM';
19716 return shadowMapTypeDefine;
19720 function generateEnvMapTypeDefine( parameters ) {
19722 let envMapTypeDefine =
'ENVMAP_TYPE_CUBE';
19724 if ( parameters.envMap ) {
19726 switch ( parameters.envMapMode ) {
19730 envMapTypeDefine =
'ENVMAP_TYPE_CUBE';
19733 case CubeUVReflectionMapping:
19734 envMapTypeDefine =
'ENVMAP_TYPE_CUBE_UV';
19741 return envMapTypeDefine;
19745 function generateEnvMapModeDefine( parameters ) {
19747 let envMapModeDefine =
'ENVMAP_MODE_REFLECTION';
19749 if ( parameters.envMap ) {
19751 switch ( parameters.envMapMode ) {
19755 envMapModeDefine =
'ENVMAP_MODE_REFRACTION';
19762 return envMapModeDefine;
19766 function generateEnvMapBlendingDefine( parameters ) {
19768 let envMapBlendingDefine =
'ENVMAP_BLENDING_NONE';
19770 if ( parameters.envMap ) {
19772 switch ( parameters.combine ) {
19775 envMapBlendingDefine =
'ENVMAP_BLENDING_MULTIPLY';
19779 envMapBlendingDefine =
'ENVMAP_BLENDING_MIX';
19783 envMapBlendingDefine =
'ENVMAP_BLENDING_ADD';
19790 return envMapBlendingDefine;
19794 function generateCubeUVSize( parameters ) {
19796 const imageHeight = parameters.envMapCubeUVHeight;
19798 if ( imageHeight ===
null )
return null;
19800 const maxMip =
Math.log2( imageHeight ) - 2;
19802 const texelHeight = 1.0 / imageHeight;
19804 const texelWidth = 1.0 / ( 3 *
Math.max(
Math.pow( 2, maxMip ), 7 * 16 ) );
19806 return { texelWidth, texelHeight, maxMip };
19810 function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) {
19815 const gl = renderer.getContext();
19817 const defines = parameters.defines;
19819 let vertexShader = parameters.vertexShader;
19820 let fragmentShader = parameters.fragmentShader;
19822 const shadowMapTypeDefine = generateShadowMapTypeDefine( parameters );
19823 const envMapTypeDefine = generateEnvMapTypeDefine( parameters );
19824 const envMapModeDefine = generateEnvMapModeDefine( parameters );
19825 const envMapBlendingDefine = generateEnvMapBlendingDefine( parameters );
19826 const envMapCubeUVSize = generateCubeUVSize( parameters );
19828 const customExtensions = parameters.isWebGL2 ?
'' : generateExtensions( parameters );
19830 const customVertexExtensions = generateVertexExtensions( parameters );
19832 const customDefines = generateDefines( defines );
19834 const program = gl.createProgram();
19836 let prefixVertex, prefixFragment;
19837 let versionString = parameters.glslVersion ?
'#version ' + parameters.glslVersion +
'\n' :
'';
19839 if ( parameters.isRawShaderMaterial ) {
19843 '#define SHADER_TYPE ' + parameters.shaderType,
19844 '#define SHADER_NAME ' + parameters.shaderName,
19848 ].filter( filterEmptyLine ).join(
'\n' );
19850 if ( prefixVertex.length > 0 ) {
19852 prefixVertex +=
'\n';
19860 '#define SHADER_TYPE ' + parameters.shaderType,
19861 '#define SHADER_NAME ' + parameters.shaderName,
19865 ].filter( filterEmptyLine ).join(
'\n' );
19867 if ( prefixFragment.length > 0 ) {
19869 prefixFragment +=
'\n';
19877 generatePrecision( parameters ),
19879 '#define SHADER_TYPE ' + parameters.shaderType,
19880 '#define SHADER_NAME ' + parameters.shaderName,
19884 parameters.extensionClipCullDistance ?
'#define USE_CLIP_DISTANCE' :
'',
19885 parameters.batching ?
'#define USE_BATCHING' :
'',
19886 parameters.instancing ?
'#define USE_INSTANCING' :
'',
19887 parameters.instancingColor ?
'#define USE_INSTANCING_COLOR' :
'',
19889 parameters.useFog && parameters.fog ?
'#define USE_FOG' :
'',
19890 parameters.useFog && parameters.fogExp2 ?
'#define FOG_EXP2' :
'',
19892 parameters.map ?
'#define USE_MAP' :
'',
19893 parameters.envMap ?
'#define USE_ENVMAP' :
'',
19894 parameters.envMap ?
'#define ' + envMapModeDefine :
'',
19895 parameters.lightMap ?
'#define USE_LIGHTMAP' :
'',
19896 parameters.aoMap ?
'#define USE_AOMAP' :
'',
19897 parameters.bumpMap ?
'#define USE_BUMPMAP' :
'',
19898 parameters.normalMap ?
'#define USE_NORMALMAP' :
'',
19899 parameters.normalMapObjectSpace ?
'#define USE_NORMALMAP_OBJECTSPACE' :
'',
19900 parameters.normalMapTangentSpace ?
'#define USE_NORMALMAP_TANGENTSPACE' :
'',
19901 parameters.displacementMap ?
'#define USE_DISPLACEMENTMAP' :
'',
19902 parameters.emissiveMap ?
'#define USE_EMISSIVEMAP' :
'',
19904 parameters.anisotropy ?
'#define USE_ANISOTROPY' :
'',
19905 parameters.anisotropyMap ?
'#define USE_ANISOTROPYMAP' :
'',
19907 parameters.clearcoatMap ?
'#define USE_CLEARCOATMAP' :
'',
19908 parameters.clearcoatRoughnessMap ?
'#define USE_CLEARCOAT_ROUGHNESSMAP' :
'',
19909 parameters.clearcoatNormalMap ?
'#define USE_CLEARCOAT_NORMALMAP' :
'',
19911 parameters.iridescenceMap ?
'#define USE_IRIDESCENCEMAP' :
'',
19912 parameters.iridescenceThicknessMap ?
'#define USE_IRIDESCENCE_THICKNESSMAP' :
'',
19914 parameters.specularMap ?
'#define USE_SPECULARMAP' :
'',
19915 parameters.specularColorMap ?
'#define USE_SPECULAR_COLORMAP' :
'',
19916 parameters.specularIntensityMap ?
'#define USE_SPECULAR_INTENSITYMAP' :
'',
19918 parameters.roughnessMap ?
'#define USE_ROUGHNESSMAP' :
'',
19919 parameters.metalnessMap ?
'#define USE_METALNESSMAP' :
'',
19920 parameters.alphaMap ?
'#define USE_ALPHAMAP' :
'',
19921 parameters.alphaHash ?
'#define USE_ALPHAHASH' :
'',
19923 parameters.transmission ?
'#define USE_TRANSMISSION' :
'',
19924 parameters.transmissionMap ?
'#define USE_TRANSMISSIONMAP' :
'',
19925 parameters.thicknessMap ?
'#define USE_THICKNESSMAP' :
'',
19927 parameters.sheenColorMap ?
'#define USE_SHEEN_COLORMAP' :
'',
19928 parameters.sheenRoughnessMap ?
'#define USE_SHEEN_ROUGHNESSMAP' :
'',
19932 parameters.mapUv ?
'#define MAP_UV ' + parameters.mapUv :
'',
19933 parameters.alphaMapUv ?
'#define ALPHAMAP_UV ' + parameters.alphaMapUv :
'',
19934 parameters.lightMapUv ?
'#define LIGHTMAP_UV ' + parameters.lightMapUv :
'',
19935 parameters.aoMapUv ?
'#define AOMAP_UV ' + parameters.aoMapUv :
'',
19936 parameters.emissiveMapUv ?
'#define EMISSIVEMAP_UV ' + parameters.emissiveMapUv :
'',
19937 parameters.bumpMapUv ?
'#define BUMPMAP_UV ' + parameters.bumpMapUv :
'',
19938 parameters.normalMapUv ?
'#define NORMALMAP_UV ' + parameters.normalMapUv :
'',
19939 parameters.displacementMapUv ?
'#define DISPLACEMENTMAP_UV ' + parameters.displacementMapUv :
'',
19941 parameters.metalnessMapUv ?
'#define METALNESSMAP_UV ' + parameters.metalnessMapUv :
'',
19942 parameters.roughnessMapUv ?
'#define ROUGHNESSMAP_UV ' + parameters.roughnessMapUv :
'',
19944 parameters.anisotropyMapUv ?
'#define ANISOTROPYMAP_UV ' + parameters.anisotropyMapUv :
'',
19946 parameters.clearcoatMapUv ?
'#define CLEARCOATMAP_UV ' + parameters.clearcoatMapUv :
'',
19947 parameters.clearcoatNormalMapUv ?
'#define CLEARCOAT_NORMALMAP_UV ' + parameters.clearcoatNormalMapUv :
'',
19948 parameters.clearcoatRoughnessMapUv ?
'#define CLEARCOAT_ROUGHNESSMAP_UV ' + parameters.clearcoatRoughnessMapUv :
'',
19950 parameters.iridescenceMapUv ?
'#define IRIDESCENCEMAP_UV ' + parameters.iridescenceMapUv :
'',
19951 parameters.iridescenceThicknessMapUv ?
'#define IRIDESCENCE_THICKNESSMAP_UV ' + parameters.iridescenceThicknessMapUv :
'',
19953 parameters.sheenColorMapUv ?
'#define SHEEN_COLORMAP_UV ' + parameters.sheenColorMapUv :
'',
19954 parameters.sheenRoughnessMapUv ?
'#define SHEEN_ROUGHNESSMAP_UV ' + parameters.sheenRoughnessMapUv :
'',
19956 parameters.specularMapUv ?
'#define SPECULARMAP_UV ' + parameters.specularMapUv :
'',
19957 parameters.specularColorMapUv ?
'#define SPECULAR_COLORMAP_UV ' + parameters.specularColorMapUv :
'',
19958 parameters.specularIntensityMapUv ?
'#define SPECULAR_INTENSITYMAP_UV ' + parameters.specularIntensityMapUv :
'',
19960 parameters.transmissionMapUv ?
'#define TRANSMISSIONMAP_UV ' + parameters.transmissionMapUv :
'',
19961 parameters.thicknessMapUv ?
'#define THICKNESSMAP_UV ' + parameters.thicknessMapUv :
'',
19965 parameters.vertexTangents && parameters.flatShading ===
false ?
'#define USE_TANGENT' :
'',
19966 parameters.vertexColors ?
'#define USE_COLOR' :
'',
19967 parameters.vertexAlphas ?
'#define USE_COLOR_ALPHA' :
'',
19968 parameters.vertexUv1s ?
'#define USE_UV1' :
'',
19969 parameters.vertexUv2s ?
'#define USE_UV2' :
'',
19970 parameters.vertexUv3s ?
'#define USE_UV3' :
'',
19972 parameters.pointsUvs ?
'#define USE_POINTS_UV' :
'',
19974 parameters.flatShading ?
'#define FLAT_SHADED' :
'',
19976 parameters.skinning ?
'#define USE_SKINNING' :
'',
19978 parameters.morphTargets ?
'#define USE_MORPHTARGETS' :
'',
19979 parameters.morphNormals && parameters.flatShading ===
false ?
'#define USE_MORPHNORMALS' :
'',
19980 ( parameters.morphColors && parameters.isWebGL2 ) ?
'#define USE_MORPHCOLORS' :
'',
19981 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ?
'#define MORPHTARGETS_TEXTURE' :
'',
19982 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ?
'#define MORPHTARGETS_TEXTURE_STRIDE ' + parameters.morphTextureStride :
'',
19983 ( parameters.morphTargetsCount > 0 && parameters.isWebGL2 ) ?
'#define MORPHTARGETS_COUNT ' + parameters.morphTargetsCount :
'',
19984 parameters.doubleSided ?
'#define DOUBLE_SIDED' :
'',
19985 parameters.flipSided ?
'#define FLIP_SIDED' :
'',
19987 parameters.shadowMapEnabled ?
'#define USE_SHADOWMAP' :
'',
19988 parameters.shadowMapEnabled ?
'#define ' + shadowMapTypeDefine :
'',
19990 parameters.sizeAttenuation ?
'#define USE_SIZEATTENUATION' :
'',
19992 parameters.numLightProbes > 0 ?
'#define USE_LIGHT_PROBES' :
'',
19994 parameters.useLegacyLights ?
'#define LEGACY_LIGHTS' :
'',
19996 parameters.logarithmicDepthBuffer ?
'#define USE_LOGDEPTHBUF' :
'',
19997 ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ?
'#define USE_LOGDEPTHBUF_EXT' :
'',
19999 'uniform mat4 modelMatrix;',
20000 'uniform mat4 modelViewMatrix;',
20001 'uniform mat4 projectionMatrix;',
20002 'uniform mat4 viewMatrix;',
20003 'uniform mat3 normalMatrix;',
20004 'uniform vec3 cameraPosition;',
20005 'uniform bool isOrthographic;',
20007 '#ifdef USE_INSTANCING',
20009 ' attribute mat4 instanceMatrix;',
20013 '#ifdef USE_INSTANCING_COLOR',
20015 ' attribute vec3 instanceColor;',
20019 'attribute vec3 position;',
20020 'attribute vec3 normal;',
20021 'attribute vec2 uv;',
20025 ' attribute vec2 uv1;',
20031 ' attribute vec2 uv2;',
20037 ' attribute vec2 uv3;',
20041 '#ifdef USE_TANGENT',
20043 ' attribute vec4 tangent;',
20047 '#if defined( USE_COLOR_ALPHA )',
20049 ' attribute vec4 color;',
20051 '#elif defined( USE_COLOR )',
20053 ' attribute vec3 color;',
20057 '#if ( defined( USE_MORPHTARGETS ) && ! defined( MORPHTARGETS_TEXTURE ) )',
20059 ' attribute vec3 morphTarget0;',
20060 ' attribute vec3 morphTarget1;',
20061 ' attribute vec3 morphTarget2;',
20062 ' attribute vec3 morphTarget3;',
20064 ' #ifdef USE_MORPHNORMALS',
20066 ' attribute vec3 morphNormal0;',
20067 ' attribute vec3 morphNormal1;',
20068 ' attribute vec3 morphNormal2;',
20069 ' attribute vec3 morphNormal3;',
20073 ' attribute vec3 morphTarget4;',
20074 ' attribute vec3 morphTarget5;',
20075 ' attribute vec3 morphTarget6;',
20076 ' attribute vec3 morphTarget7;',
20082 '#ifdef USE_SKINNING',
20084 ' attribute vec4 skinIndex;',
20085 ' attribute vec4 skinWeight;',
20091 ].filter( filterEmptyLine ).join(
'\n' );
20097 generatePrecision( parameters ),
20099 '#define SHADER_TYPE ' + parameters.shaderType,
20100 '#define SHADER_NAME ' + parameters.shaderName,
20104 parameters.useFog && parameters.fog ?
'#define USE_FOG' :
'',
20105 parameters.useFog && parameters.fogExp2 ?
'#define FOG_EXP2' :
'',
20107 parameters.map ?
'#define USE_MAP' :
'',
20108 parameters.matcap ?
'#define USE_MATCAP' :
'',
20109 parameters.envMap ?
'#define USE_ENVMAP' :
'',
20110 parameters.envMap ?
'#define ' + envMapTypeDefine :
'',
20111 parameters.envMap ?
'#define ' + envMapModeDefine :
'',
20112 parameters.envMap ?
'#define ' + envMapBlendingDefine :
'',
20113 envMapCubeUVSize ?
'#define CUBEUV_TEXEL_WIDTH ' + envMapCubeUVSize.texelWidth :
'',
20114 envMapCubeUVSize ?
'#define CUBEUV_TEXEL_HEIGHT ' + envMapCubeUVSize.texelHeight :
'',
20115 envMapCubeUVSize ?
'#define CUBEUV_MAX_MIP ' + envMapCubeUVSize.maxMip +
'.0' :
'',
20116 parameters.lightMap ?
'#define USE_LIGHTMAP' :
'',
20117 parameters.aoMap ?
'#define USE_AOMAP' :
'',
20118 parameters.bumpMap ?
'#define USE_BUMPMAP' :
'',
20119 parameters.normalMap ?
'#define USE_NORMALMAP' :
'',
20120 parameters.normalMapObjectSpace ?
'#define USE_NORMALMAP_OBJECTSPACE' :
'',
20121 parameters.normalMapTangentSpace ?
'#define USE_NORMALMAP_TANGENTSPACE' :
'',
20122 parameters.emissiveMap ?
'#define USE_EMISSIVEMAP' :
'',
20124 parameters.anisotropy ?
'#define USE_ANISOTROPY' :
'',
20125 parameters.anisotropyMap ?
'#define USE_ANISOTROPYMAP' :
'',
20127 parameters.clearcoat ?
'#define USE_CLEARCOAT' :
'',
20128 parameters.clearcoatMap ?
'#define USE_CLEARCOATMAP' :
'',
20129 parameters.clearcoatRoughnessMap ?
'#define USE_CLEARCOAT_ROUGHNESSMAP' :
'',
20130 parameters.clearcoatNormalMap ?
'#define USE_CLEARCOAT_NORMALMAP' :
'',
20132 parameters.iridescence ?
'#define USE_IRIDESCENCE' :
'',
20133 parameters.iridescenceMap ?
'#define USE_IRIDESCENCEMAP' :
'',
20134 parameters.iridescenceThicknessMap ?
'#define USE_IRIDESCENCE_THICKNESSMAP' :
'',
20136 parameters.specularMap ?
'#define USE_SPECULARMAP' :
'',
20137 parameters.specularColorMap ?
'#define USE_SPECULAR_COLORMAP' :
'',
20138 parameters.specularIntensityMap ?
'#define USE_SPECULAR_INTENSITYMAP' :
'',
20140 parameters.roughnessMap ?
'#define USE_ROUGHNESSMAP' :
'',
20141 parameters.metalnessMap ?
'#define USE_METALNESSMAP' :
'',
20143 parameters.alphaMap ?
'#define USE_ALPHAMAP' :
'',
20144 parameters.alphaTest ?
'#define USE_ALPHATEST' :
'',
20145 parameters.alphaHash ?
'#define USE_ALPHAHASH' :
'',
20147 parameters.sheen ?
'#define USE_SHEEN' :
'',
20148 parameters.sheenColorMap ?
'#define USE_SHEEN_COLORMAP' :
'',
20149 parameters.sheenRoughnessMap ?
'#define USE_SHEEN_ROUGHNESSMAP' :
'',
20151 parameters.transmission ?
'#define USE_TRANSMISSION' :
'',
20152 parameters.transmissionMap ?
'#define USE_TRANSMISSIONMAP' :
'',
20153 parameters.thicknessMap ?
'#define USE_THICKNESSMAP' :
'',
20155 parameters.vertexTangents && parameters.flatShading ===
false ?
'#define USE_TANGENT' :
'',
20156 parameters.vertexColors || parameters.instancingColor ?
'#define USE_COLOR' :
'',
20157 parameters.vertexAlphas ?
'#define USE_COLOR_ALPHA' :
'',
20158 parameters.vertexUv1s ?
'#define USE_UV1' :
'',
20159 parameters.vertexUv2s ?
'#define USE_UV2' :
'',
20160 parameters.vertexUv3s ?
'#define USE_UV3' :
'',
20162 parameters.pointsUvs ?
'#define USE_POINTS_UV' :
'',
20164 parameters.gradientMap ?
'#define USE_GRADIENTMAP' :
'',
20166 parameters.flatShading ?
'#define FLAT_SHADED' :
'',
20168 parameters.doubleSided ?
'#define DOUBLE_SIDED' :
'',
20169 parameters.flipSided ?
'#define FLIP_SIDED' :
'',
20171 parameters.shadowMapEnabled ?
'#define USE_SHADOWMAP' :
'',
20172 parameters.shadowMapEnabled ?
'#define ' + shadowMapTypeDefine :
'',
20174 parameters.premultipliedAlpha ?
'#define PREMULTIPLIED_ALPHA' :
'',
20176 parameters.numLightProbes > 0 ?
'#define USE_LIGHT_PROBES' :
'',
20178 parameters.useLegacyLights ?
'#define LEGACY_LIGHTS' :
'',
20180 parameters.decodeVideoTexture ?
'#define DECODE_VIDEO_TEXTURE' :
'',
20182 parameters.logarithmicDepthBuffer ?
'#define USE_LOGDEPTHBUF' :
'',
20183 ( parameters.logarithmicDepthBuffer && parameters.rendererExtensionFragDepth ) ?
'#define USE_LOGDEPTHBUF_EXT' :
'',
20185 'uniform mat4 viewMatrix;',
20186 'uniform vec3 cameraPosition;',
20187 'uniform bool isOrthographic;',
20189 ( parameters.toneMapping !== NoToneMapping ) ?
'#define TONE_MAPPING' :
'',
20190 ( parameters.toneMapping !== NoToneMapping ) ?
ShaderChunk[
'tonemapping_pars_fragment' ] :
'',
20191 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction(
'toneMapping', parameters.toneMapping ) :
'',
20193 parameters.dithering ?
'#define DITHERING' :
'',
20194 parameters.opaque ?
'#define OPAQUE' :
'',
20197 getTexelEncodingFunction(
'linearToOutputTexel', parameters.outputColorSpace ),
20199 parameters.useDepthPacking ?
'#define DEPTH_PACKING ' + parameters.depthPacking :
'',
20203 ].filter( filterEmptyLine ).join(
'\n' );
20207 vertexShader = resolveIncludes( vertexShader );
20208 vertexShader = replaceLightNums( vertexShader, parameters );
20209 vertexShader = replaceClippingPlaneNums( vertexShader, parameters );
20211 fragmentShader = resolveIncludes( fragmentShader );
20212 fragmentShader = replaceLightNums( fragmentShader, parameters );
20213 fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters );
20215 vertexShader = unrollLoops( vertexShader );
20216 fragmentShader = unrollLoops( fragmentShader );
20218 if ( parameters.isWebGL2 && parameters.isRawShaderMaterial !==
true ) {
20222 versionString =
'#version 300 es\n';
20225 customVertexExtensions,
20226 'precision mediump sampler2DArray;',
20227 '#define attribute in',
20228 '#define varying out',
20229 '#define texture2D texture'
20230 ].join(
'\n' ) +
'\n' + prefixVertex;
20233 'precision mediump sampler2DArray;',
20234 '#define varying in',
20235 ( parameters.glslVersion === GLSL3 ) ?
'' :
'layout(location = 0) out highp vec4 pc_fragColor;',
20236 ( parameters.glslVersion === GLSL3 ) ?
'' :
'#define gl_FragColor pc_fragColor',
20237 '#define gl_FragDepthEXT gl_FragDepth',
20238 '#define texture2D texture',
20239 '#define textureCube texture',
20240 '#define texture2DProj textureProj',
20241 '#define texture2DLodEXT textureLod',
20242 '#define texture2DProjLodEXT textureProjLod',
20243 '#define textureCubeLodEXT textureLod',
20244 '#define texture2DGradEXT textureGrad',
20245 '#define texture2DProjGradEXT textureProjGrad',
20246 '#define textureCubeGradEXT textureGrad'
20247 ].join(
'\n' ) +
'\n' + prefixFragment;
20251 const vertexGlsl = versionString + prefixVertex + vertexShader;
20252 const fragmentGlsl = versionString + prefixFragment + fragmentShader;
20257 const glVertexShader =
WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl );
20258 const glFragmentShader =
WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl );
20260 gl.attachShader( program, glVertexShader );
20261 gl.attachShader( program, glFragmentShader );
20265 if ( parameters.index0AttributeName !==
undefined ) {
20267 gl.bindAttribLocation( program, 0, parameters.index0AttributeName );
20269 }
else if ( parameters.morphTargets ===
true ) {
20272 gl.bindAttribLocation( program, 0,
'position' );
20276 gl.linkProgram( program );
20278 function onFirstUse(
self ) {
20281 if ( renderer.debug.checkShaderErrors ) {
20283 const programLog = gl.getProgramInfoLog( program ).trim();
20284 const vertexLog = gl.getShaderInfoLog( glVertexShader ).trim();
20285 const fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim();
20287 let runnable =
true;
20288 let haveDiagnostics =
true;
20290 if ( gl.getProgramParameter( program, gl.LINK_STATUS ) ===
false ) {
20294 if ( typeof renderer.debug.onShaderError ===
'function' ) {
20296 renderer.debug.onShaderError( gl, program, glVertexShader, glFragmentShader );
20302 const vertexErrors = getShaderErrors( gl, glVertexShader,
'vertex' );
20303 const fragmentErrors = getShaderErrors( gl, glFragmentShader,
'fragment' );
20306 'THREE.WebGLProgram: Shader Error ' + gl.getError() +
' - ' +
20307 'VALIDATE_STATUS ' + gl.getProgramParameter( program, gl.VALIDATE_STATUS ) +
'\n\n' +
20308 'Program Info Log: ' + programLog +
'\n' +
20309 vertexErrors +
'\n' +
20315 }
else if ( programLog !==
'' ) {
20317 console.warn(
'THREE.WebGLProgram: Program Info Log:', programLog );
20319 }
else if ( vertexLog ===
'' || fragmentLog ===
'' ) {
20321 haveDiagnostics =
false;
20325 if ( haveDiagnostics ) {
20327 self.diagnostics = {
20329 runnable: runnable,
20331 programLog: programLog,
20336 prefix: prefixVertex
20343 prefix: prefixFragment
20359 gl.deleteShader( glVertexShader );
20360 gl.deleteShader( glFragmentShader );
20362 cachedUniforms =
new WebGLUniforms( gl, program );
20363 cachedAttributes = fetchAttributeLocations( gl, program );
20369 let cachedUniforms;
20371 this.getUniforms =
function () {
20376 onFirstUse(
this );
20380 return cachedUniforms;
20386 let cachedAttributes;
20388 this.getAttributes =
function () {
20390 if ( cachedAttributes ===
undefined ) {
20393 onFirstUse(
this );
20397 return cachedAttributes;
20404 let programReady = ( parameters.rendererExtensionParallelShaderCompile === false );
20406 this.isReady =
function () {
20408 if ( programReady ===
false ) {
20410 programReady = gl.getProgramParameter( program, COMPLETION_STATUS_KHR );
20414 return programReady;
20420 this.destroy =
function () {
20422 bindingStates.releaseStatesOfProgram(
this );
20424 gl.deleteProgram( program );
20431 this.type = parameters.shaderType;
20432 this.name = parameters.shaderName;
20433 this.
id = programIdCount ++;
20434 this.cacheKey = cacheKey;
20435 this.usedTimes = 1;
20436 this.program = program;
20437 this.vertexShader = glVertexShader;
20438 this.fragmentShader = glFragmentShader;
20446 class WebGLShaderCache {
20450 this.shaderCache =
new Map();
20451 this.materialCache =
new Map();
20457 const vertexShader = material.vertexShader;
20458 const fragmentShader = material.fragmentShader;
20460 const vertexShaderStage = this._getShaderStage( vertexShader );
20461 const fragmentShaderStage = this._getShaderStage( fragmentShader );
20463 const materialShaders = this._getShaderCacheForMaterial( material );
20465 if ( materialShaders.has( vertexShaderStage ) ===
false ) {
20467 materialShaders.add( vertexShaderStage );
20468 vertexShaderStage.usedTimes ++;
20472 if ( materialShaders.has( fragmentShaderStage ) ===
false ) {
20474 materialShaders.add( fragmentShaderStage );
20475 fragmentShaderStage.usedTimes ++;
20483 remove( material ) {
20485 const materialShaders = this.materialCache.get( material );
20487 for (
const shaderStage of materialShaders ) {
20489 shaderStage.usedTimes --;
20491 if ( shaderStage.usedTimes === 0 ) this.shaderCache.delete( shaderStage.code );
20495 this.materialCache.delete( material );
20501 getVertexShaderID( material ) {
20503 return this._getShaderStage( material.vertexShader ).id;
20507 getFragmentShaderID( material ) {
20509 return this._getShaderStage( material.fragmentShader ).id;
20515 this.shaderCache.clear();
20516 this.materialCache.clear();
20520 _getShaderCacheForMaterial( material ) {
20522 const cache = this.materialCache;
20523 let
set =
cache.get( material );
20528 cache.set( material,
set );
20536 _getShaderStage( code ) {
20538 const cache = this.shaderCache;
20539 let stage =
cache.get( code );
20543 stage =
new WebGLShaderStage( code );
20544 cache.set( code, stage );
20554 class WebGLShaderStage {
20556 constructor( code ) {
20558 this.
id = _id$1 ++;
20561 this.usedTimes = 0;
20567 function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping ) {
20569 const _programLayers =
new Layers();
20570 const _customShaders =
new WebGLShaderCache();
20571 const programs = [];
20573 const IS_WEBGL2 = capabilities.isWebGL2;
20574 const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer;
20575 const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures;
20577 let precision = capabilities.precision;
20579 const shaderIDs = {
20581 MeshDistanceMaterial:
'distanceRGBA',
20586 MeshToonMaterial:
'toon',
20587 MeshStandardMaterial:
'physical',
20588 MeshPhysicalMaterial:
'physical',
20589 MeshMatcapMaterial:
'matcap',
20592 PointsMaterial:
'points',
20593 ShadowMaterial:
'shadow',
20597 function getChannel( value ) {
20599 if ( value === 0 )
return 'uv';
20601 return `uv${ value }`;
20605 function getParameters( material, lights, shadows, scene,
object ) {
20607 const fog = scene.fog;
20608 const geometry =
object.geometry;
20609 const environment = material.isMeshStandardMaterial ? scene.environment :
null;
20611 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).
get( material.envMap || environment );
20612 const envMapCubeUVHeight = ( !! envMap ) && ( envMap.mapping === CubeUVReflectionMapping ) ? envMap.image.height :
null;
20614 const shaderID = shaderIDs[ material.type ];
20619 if ( material.precision !==
null ) {
20621 precision = capabilities.getMaxPrecision( material.precision );
20623 if ( precision !== material.precision ) {
20625 console.warn(
'THREE.WebGLProgram.getParameters:', material.precision,
'not supported, using', precision,
'instead.' );
20633 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
20634 const morphTargetsCount = ( morphAttribute !==
undefined ) ? morphAttribute.length : 0;
20636 let morphTextureStride = 0;
20638 if ( geometry.morphAttributes.position !==
undefined ) morphTextureStride = 1;
20639 if ( geometry.morphAttributes.normal !==
undefined ) morphTextureStride = 2;
20640 if ( geometry.morphAttributes.color !==
undefined ) morphTextureStride = 3;
20644 let vertexShader, fragmentShader;
20645 let customVertexShaderID, customFragmentShaderID;
20651 vertexShader = shader.vertexShader;
20652 fragmentShader = shader.fragmentShader;
20656 vertexShader = material.vertexShader;
20657 fragmentShader = material.fragmentShader;
20659 _customShaders.update( material );
20661 customVertexShaderID = _customShaders.getVertexShaderID( material );
20662 customFragmentShaderID = _customShaders.getFragmentShaderID( material );
20666 const currentRenderTarget = renderer.getRenderTarget();
20668 const IS_INSTANCEDMESH =
object.isInstancedMesh ===
true;
20669 const IS_BATCHEDMESH =
object.isBatchedMesh ===
true;
20671 const HAS_MAP = !! material.map;
20672 const HAS_MATCAP = !! material.matcap;
20673 const HAS_ENVMAP = !! envMap;
20674 const HAS_AOMAP = !! material.aoMap;
20675 const HAS_LIGHTMAP = !! material.lightMap;
20676 const HAS_BUMPMAP = !! material.bumpMap;
20677 const HAS_NORMALMAP = !! material.normalMap;
20678 const HAS_DISPLACEMENTMAP = !! material.displacementMap;
20679 const HAS_EMISSIVEMAP = !! material.emissiveMap;
20681 const HAS_METALNESSMAP = !! material.metalnessMap;
20682 const HAS_ROUGHNESSMAP = !! material.roughnessMap;
20684 const HAS_ANISOTROPY = material.anisotropy > 0;
20685 const HAS_CLEARCOAT = material.clearcoat > 0;
20686 const HAS_IRIDESCENCE = material.iridescence > 0;
20687 const HAS_SHEEN = material.sheen > 0;
20688 const HAS_TRANSMISSION = material.transmission > 0;
20690 const HAS_ANISOTROPYMAP = HAS_ANISOTROPY && !! material.anisotropyMap;
20692 const HAS_CLEARCOATMAP = HAS_CLEARCOAT && !! material.clearcoatMap;
20693 const HAS_CLEARCOAT_NORMALMAP = HAS_CLEARCOAT && !! material.clearcoatNormalMap;
20694 const HAS_CLEARCOAT_ROUGHNESSMAP = HAS_CLEARCOAT && !! material.clearcoatRoughnessMap;
20696 const HAS_IRIDESCENCEMAP = HAS_IRIDESCENCE && !! material.iridescenceMap;
20697 const HAS_IRIDESCENCE_THICKNESSMAP = HAS_IRIDESCENCE && !! material.iridescenceThicknessMap;
20699 const HAS_SHEEN_COLORMAP = HAS_SHEEN && !! material.sheenColorMap;
20700 const HAS_SHEEN_ROUGHNESSMAP = HAS_SHEEN && !! material.sheenRoughnessMap;
20702 const HAS_SPECULARMAP = !! material.specularMap;
20703 const HAS_SPECULAR_COLORMAP = !! material.specularColorMap;
20704 const HAS_SPECULAR_INTENSITYMAP = !! material.specularIntensityMap;
20706 const HAS_TRANSMISSIONMAP = HAS_TRANSMISSION && !! material.transmissionMap;
20707 const HAS_THICKNESSMAP = HAS_TRANSMISSION && !! material.thicknessMap;
20709 const HAS_GRADIENTMAP = !! material.gradientMap;
20711 const HAS_ALPHAMAP = !! material.alphaMap;
20713 const HAS_ALPHATEST = material.alphaTest > 0;
20715 const HAS_ALPHAHASH = !! material.alphaHash;
20717 const HAS_EXTENSIONS = !! material.extensions;
20719 const HAS_ATTRIBUTE_UV1 = !! geometry.attributes.uv1;
20720 const HAS_ATTRIBUTE_UV2 = !! geometry.attributes.uv2;
20721 const HAS_ATTRIBUTE_UV3 = !! geometry.attributes.uv3;
20723 let toneMapping = NoToneMapping;
20725 if ( material.toneMapped ) {
20727 if ( currentRenderTarget ===
null || currentRenderTarget.isXRRenderTarget ===
true ) {
20729 toneMapping = renderer.toneMapping;
20735 const parameters = {
20737 isWebGL2: IS_WEBGL2,
20739 shaderID: shaderID,
20740 shaderType: material.type,
20741 shaderName: material.name,
20743 vertexShader: vertexShader,
20744 fragmentShader: fragmentShader,
20745 defines: material.defines,
20747 customVertexShaderID: customVertexShaderID,
20748 customFragmentShaderID: customFragmentShaderID,
20750 isRawShaderMaterial: material.isRawShaderMaterial ===
true,
20751 glslVersion: material.glslVersion,
20753 precision: precision,
20755 batching: IS_BATCHEDMESH,
20756 instancing: IS_INSTANCEDMESH,
20757 instancingColor: IS_INSTANCEDMESH &&
object.instanceColor !==
null,
20759 supportsVertexTextures: SUPPORTS_VERTEX_TEXTURES,
20760 outputColorSpace: ( currentRenderTarget === null ) ? renderer.outputColorSpace : ( currentRenderTarget.isXRRenderTarget === true ? currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace ),
20763 matcap: HAS_MATCAP,
20764 envMap: HAS_ENVMAP,
20765 envMapMode: HAS_ENVMAP && envMap.mapping,
20766 envMapCubeUVHeight: envMapCubeUVHeight,
20768 lightMap: HAS_LIGHTMAP,
20769 bumpMap: HAS_BUMPMAP,
20770 normalMap: HAS_NORMALMAP,
20771 displacementMap: SUPPORTS_VERTEX_TEXTURES && HAS_DISPLACEMENTMAP,
20772 emissiveMap: HAS_EMISSIVEMAP,
20774 normalMapObjectSpace: HAS_NORMALMAP && material.normalMapType === ObjectSpaceNormalMap,
20775 normalMapTangentSpace: HAS_NORMALMAP && material.normalMapType === TangentSpaceNormalMap,
20777 metalnessMap: HAS_METALNESSMAP,
20778 roughnessMap: HAS_ROUGHNESSMAP,
20780 anisotropy: HAS_ANISOTROPY,
20781 anisotropyMap: HAS_ANISOTROPYMAP,
20783 clearcoat: HAS_CLEARCOAT,
20784 clearcoatMap: HAS_CLEARCOATMAP,
20785 clearcoatNormalMap: HAS_CLEARCOAT_NORMALMAP,
20786 clearcoatRoughnessMap: HAS_CLEARCOAT_ROUGHNESSMAP,
20788 iridescence: HAS_IRIDESCENCE,
20789 iridescenceMap: HAS_IRIDESCENCEMAP,
20790 iridescenceThicknessMap: HAS_IRIDESCENCE_THICKNESSMAP,
20793 sheenColorMap: HAS_SHEEN_COLORMAP,
20794 sheenRoughnessMap: HAS_SHEEN_ROUGHNESSMAP,
20796 specularMap: HAS_SPECULARMAP,
20797 specularColorMap: HAS_SPECULAR_COLORMAP,
20798 specularIntensityMap: HAS_SPECULAR_INTENSITYMAP,
20800 transmission: HAS_TRANSMISSION,
20801 transmissionMap: HAS_TRANSMISSIONMAP,
20802 thicknessMap: HAS_THICKNESSMAP,
20804 gradientMap: HAS_GRADIENTMAP,
20806 opaque: material.transparent === false && material.blending ===
NormalBlending,
20808 alphaMap: HAS_ALPHAMAP,
20809 alphaTest: HAS_ALPHATEST,
20810 alphaHash: HAS_ALPHAHASH,
20812 combine: material.combine,
20816 mapUv: HAS_MAP && getChannel( material.map.channel ),
20817 aoMapUv: HAS_AOMAP && getChannel( material.aoMap.channel ),
20818 lightMapUv: HAS_LIGHTMAP && getChannel( material.lightMap.channel ),
20819 bumpMapUv: HAS_BUMPMAP && getChannel( material.bumpMap.channel ),
20820 normalMapUv: HAS_NORMALMAP && getChannel( material.normalMap.channel ),
20821 displacementMapUv: HAS_DISPLACEMENTMAP && getChannel( material.displacementMap.channel ),
20822 emissiveMapUv: HAS_EMISSIVEMAP && getChannel( material.emissiveMap.channel ),
20824 metalnessMapUv: HAS_METALNESSMAP && getChannel( material.metalnessMap.channel ),
20825 roughnessMapUv: HAS_ROUGHNESSMAP && getChannel( material.roughnessMap.channel ),
20827 anisotropyMapUv: HAS_ANISOTROPYMAP && getChannel( material.anisotropyMap.channel ),
20829 clearcoatMapUv: HAS_CLEARCOATMAP && getChannel( material.clearcoatMap.channel ),
20830 clearcoatNormalMapUv: HAS_CLEARCOAT_NORMALMAP && getChannel( material.clearcoatNormalMap.channel ),
20831 clearcoatRoughnessMapUv: HAS_CLEARCOAT_ROUGHNESSMAP && getChannel( material.clearcoatRoughnessMap.channel ),
20833 iridescenceMapUv: HAS_IRIDESCENCEMAP && getChannel( material.iridescenceMap.channel ),
20834 iridescenceThicknessMapUv: HAS_IRIDESCENCE_THICKNESSMAP && getChannel( material.iridescenceThicknessMap.channel ),
20836 sheenColorMapUv: HAS_SHEEN_COLORMAP && getChannel( material.sheenColorMap.channel ),
20837 sheenRoughnessMapUv: HAS_SHEEN_ROUGHNESSMAP && getChannel( material.sheenRoughnessMap.channel ),
20839 specularMapUv: HAS_SPECULARMAP && getChannel( material.specularMap.channel ),
20840 specularColorMapUv: HAS_SPECULAR_COLORMAP && getChannel( material.specularColorMap.channel ),
20841 specularIntensityMapUv: HAS_SPECULAR_INTENSITYMAP && getChannel( material.specularIntensityMap.channel ),
20843 transmissionMapUv: HAS_TRANSMISSIONMAP && getChannel( material.transmissionMap.channel ),
20844 thicknessMapUv: HAS_THICKNESSMAP && getChannel( material.thicknessMap.channel ),
20846 alphaMapUv: HAS_ALPHAMAP && getChannel( material.alphaMap.channel ),
20850 vertexTangents: !! geometry.attributes.tangent && ( HAS_NORMALMAP || HAS_ANISOTROPY ),
20851 vertexColors: material.vertexColors,
20852 vertexAlphas: material.vertexColors === true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4,
20853 vertexUv1s: HAS_ATTRIBUTE_UV1,
20854 vertexUv2s: HAS_ATTRIBUTE_UV2,
20855 vertexUv3s: HAS_ATTRIBUTE_UV3,
20857 pointsUvs:
object.isPoints === true && !! geometry.attributes.uv && ( HAS_MAP || HAS_ALPHAMAP ),
20860 useFog: material.fog === true,
20861 fogExp2: ( fog && fog.isFogExp2 ),
20863 flatShading: material.flatShading === true,
20865 sizeAttenuation: material.sizeAttenuation === true,
20866 logarithmicDepthBuffer: logarithmicDepthBuffer,
20868 skinning:
object.isSkinnedMesh === true,
20872 morphColors: geometry.morphAttributes.color !==
undefined,
20873 morphTargetsCount: morphTargetsCount,
20874 morphTextureStride: morphTextureStride,
20876 numDirLights: lights.directional.length,
20877 numPointLights: lights.point.length,
20878 numSpotLights: lights.spot.length,
20879 numSpotLightMaps: lights.spotLightMap.length,
20880 numRectAreaLights: lights.rectArea.length,
20881 numHemiLights: lights.hemi.length,
20883 numDirLightShadows: lights.directionalShadowMap.length,
20884 numPointLightShadows: lights.pointShadowMap.length,
20885 numSpotLightShadows: lights.spotShadowMap.length,
20886 numSpotLightShadowsWithMaps: lights.numSpotLightShadowsWithMaps,
20888 numLightProbes: lights.numLightProbes,
20890 numClippingPlanes: clipping.numPlanes,
20891 numClipIntersection: clipping.numIntersection,
20893 dithering: material.dithering,
20895 shadowMapEnabled: renderer.shadowMap.enabled && shadows.length > 0,
20896 shadowMapType: renderer.shadowMap.type,
20898 toneMapping: toneMapping,
20899 useLegacyLights: renderer._useLegacyLights,
20901 decodeVideoTexture: HAS_MAP && ( material.map.isVideoTexture === true ) && ( ColorManagement.getTransfer( material.map.colorSpace ) === SRGBTransfer ),
20903 premultipliedAlpha: material.premultipliedAlpha,
20906 flipSided: material.side ===
BackSide,
20908 useDepthPacking: material.depthPacking >= 0,
20909 depthPacking: material.depthPacking || 0,
20911 index0AttributeName: material.index0AttributeName,
20913 extensionDerivatives: HAS_EXTENSIONS && material.extensions.derivatives === true,
20914 extensionFragDepth: HAS_EXTENSIONS && material.extensions.fragDepth === true,
20915 extensionDrawBuffers: HAS_EXTENSIONS && material.extensions.drawBuffers === true,
20916 extensionShaderTextureLOD: HAS_EXTENSIONS && material.extensions.shaderTextureLOD === true,
20917 extensionClipCullDistance: HAS_EXTENSIONS && material.extensions.clipCullDistance && extensions.has(
'WEBGL_clip_cull_distance' ),
20919 rendererExtensionFragDepth: IS_WEBGL2 || extensions.has(
'EXT_frag_depth' ),
20920 rendererExtensionDrawBuffers: IS_WEBGL2 || extensions.has(
'WEBGL_draw_buffers' ),
20921 rendererExtensionShaderTextureLod: IS_WEBGL2 || extensions.has(
'EXT_shader_texture_lod' ),
20922 rendererExtensionParallelShaderCompile: extensions.has(
'KHR_parallel_shader_compile' ),
20924 customProgramCacheKey: material.customProgramCacheKey()
20932 function getProgramCacheKey( parameters ) {
20936 if ( parameters.shaderID ) {
20938 array.push( parameters.shaderID );
20942 array.push( parameters.customVertexShaderID );
20943 array.push( parameters.customFragmentShaderID );
20947 if ( parameters.defines !==
undefined ) {
20949 for (
const name in parameters.defines ) {
20951 array.push( name );
20952 array.push( parameters.defines[ name ] );
20958 if ( parameters.isRawShaderMaterial ===
false ) {
20960 getProgramCacheKeyParameters( array, parameters );
20961 getProgramCacheKeyBooleans( array, parameters );
20962 array.push( renderer.outputColorSpace );
20966 array.push( parameters.customProgramCacheKey );
20968 return array.join();
20972 function getProgramCacheKeyParameters( array, parameters ) {
20974 array.push( parameters.precision );
20975 array.push( parameters.outputColorSpace );
20976 array.push( parameters.envMapMode );
20977 array.push( parameters.envMapCubeUVHeight );
20978 array.push( parameters.mapUv );
20979 array.push( parameters.alphaMapUv );
20980 array.push( parameters.lightMapUv );
20981 array.push( parameters.aoMapUv );
20982 array.push( parameters.bumpMapUv );
20983 array.push( parameters.normalMapUv );
20984 array.push( parameters.displacementMapUv );
20985 array.push( parameters.emissiveMapUv );
20986 array.push( parameters.metalnessMapUv );
20987 array.push( parameters.roughnessMapUv );
20988 array.push( parameters.anisotropyMapUv );
20989 array.push( parameters.clearcoatMapUv );
20990 array.push( parameters.clearcoatNormalMapUv );
20991 array.push( parameters.clearcoatRoughnessMapUv );
20992 array.push( parameters.iridescenceMapUv );
20993 array.push( parameters.iridescenceThicknessMapUv );
20994 array.push( parameters.sheenColorMapUv );
20995 array.push( parameters.sheenRoughnessMapUv );
20996 array.push( parameters.specularMapUv );
20997 array.push( parameters.specularColorMapUv );
20998 array.push( parameters.specularIntensityMapUv );
20999 array.push( parameters.transmissionMapUv );
21000 array.push( parameters.thicknessMapUv );
21001 array.push( parameters.combine );
21002 array.push( parameters.fogExp2 );
21003 array.push( parameters.sizeAttenuation );
21004 array.push( parameters.morphTargetsCount );
21005 array.push( parameters.morphAttributeCount );
21006 array.push( parameters.numDirLights );
21007 array.push( parameters.numPointLights );
21008 array.push( parameters.numSpotLights );
21009 array.push( parameters.numSpotLightMaps );
21010 array.push( parameters.numHemiLights );
21011 array.push( parameters.numRectAreaLights );
21012 array.push( parameters.numDirLightShadows );
21013 array.push( parameters.numPointLightShadows );
21014 array.push( parameters.numSpotLightShadows );
21015 array.push( parameters.numSpotLightShadowsWithMaps );
21016 array.push( parameters.numLightProbes );
21017 array.push( parameters.shadowMapType );
21018 array.push( parameters.toneMapping );
21019 array.push( parameters.numClippingPlanes );
21020 array.push( parameters.numClipIntersection );
21021 array.push( parameters.depthPacking );
21025 function getProgramCacheKeyBooleans( array, parameters ) {
21027 _programLayers.disableAll();
21029 if ( parameters.isWebGL2 )
21030 _programLayers.enable( 0 );
21031 if ( parameters.supportsVertexTextures )
21032 _programLayers.enable( 1 );
21033 if ( parameters.instancing )
21034 _programLayers.enable( 2 );
21035 if ( parameters.instancingColor )
21036 _programLayers.enable( 3 );
21037 if ( parameters.matcap )
21038 _programLayers.enable( 4 );
21039 if ( parameters.envMap )
21040 _programLayers.enable( 5 );
21041 if ( parameters.normalMapObjectSpace )
21042 _programLayers.enable( 6 );
21043 if ( parameters.normalMapTangentSpace )
21044 _programLayers.enable( 7 );
21045 if ( parameters.clearcoat )
21046 _programLayers.enable( 8 );
21047 if ( parameters.iridescence )
21048 _programLayers.enable( 9 );
21049 if ( parameters.alphaTest )
21050 _programLayers.enable( 10 );
21051 if ( parameters.vertexColors )
21052 _programLayers.enable( 11 );
21053 if ( parameters.vertexAlphas )
21054 _programLayers.enable( 12 );
21055 if ( parameters.vertexUv1s )
21056 _programLayers.enable( 13 );
21057 if ( parameters.vertexUv2s )
21058 _programLayers.enable( 14 );
21059 if ( parameters.vertexUv3s )
21060 _programLayers.enable( 15 );
21061 if ( parameters.vertexTangents )
21062 _programLayers.enable( 16 );
21063 if ( parameters.anisotropy )
21064 _programLayers.enable( 17 );
21065 if ( parameters.alphaHash )
21066 _programLayers.enable( 18 );
21067 if ( parameters.batching )
21068 _programLayers.enable( 19 );
21070 array.push( _programLayers.mask );
21071 _programLayers.disableAll();
21073 if ( parameters.fog )
21074 _programLayers.enable( 0 );
21075 if ( parameters.useFog )
21076 _programLayers.enable( 1 );
21077 if ( parameters.flatShading )
21078 _programLayers.enable( 2 );
21079 if ( parameters.logarithmicDepthBuffer )
21080 _programLayers.enable( 3 );
21081 if ( parameters.skinning )
21082 _programLayers.enable( 4 );
21083 if ( parameters.morphTargets )
21084 _programLayers.enable( 5 );
21085 if ( parameters.morphNormals )
21086 _programLayers.enable( 6 );
21087 if ( parameters.morphColors )
21088 _programLayers.enable( 7 );
21089 if ( parameters.premultipliedAlpha )
21090 _programLayers.enable( 8 );
21091 if ( parameters.shadowMapEnabled )
21092 _programLayers.enable( 9 );
21093 if ( parameters.useLegacyLights )
21094 _programLayers.enable( 10 );
21095 if ( parameters.doubleSided )
21096 _programLayers.enable( 11 );
21097 if ( parameters.flipSided )
21098 _programLayers.enable( 12 );
21099 if ( parameters.useDepthPacking )
21100 _programLayers.enable( 13 );
21101 if ( parameters.dithering )
21102 _programLayers.enable( 14 );
21103 if ( parameters.transmission )
21104 _programLayers.enable( 15 );
21105 if ( parameters.sheen )
21106 _programLayers.enable( 16 );
21107 if ( parameters.opaque )
21108 _programLayers.enable( 17 );
21109 if ( parameters.pointsUvs )
21110 _programLayers.enable( 18 );
21111 if ( parameters.decodeVideoTexture )
21112 _programLayers.enable( 19 );
21114 array.push( _programLayers.mask );
21118 function getUniforms( material ) {
21120 const shaderID = shaderIDs[ material.type ];
21130 uniforms = material.uniforms;
21138 function acquireProgram( parameters, cacheKey ) {
21143 for ( let
p = 0, pl = programs.length;
p < pl;
p ++ ) {
21145 const preexistingProgram = programs[
p ];
21147 if ( preexistingProgram.cacheKey === cacheKey ) {
21149 program = preexistingProgram;
21150 ++ program.usedTimes;
21160 program =
new WebGLProgram( renderer, cacheKey, parameters, bindingStates );
21161 programs.push( program );
21169 function releaseProgram( program ) {
21171 if ( -- program.usedTimes === 0 ) {
21174 const i = programs.indexOf( program );
21175 programs[
i ] = programs[ programs.length - 1 ];
21185 function releaseShaderCache( material ) {
21187 _customShaders.remove( material );
21193 _customShaders.dispose();
21199 getProgramCacheKey: getProgramCacheKey,
21200 getUniforms: getUniforms,
21201 acquireProgram: acquireProgram,
21202 releaseProgram: releaseProgram,
21203 releaseShaderCache: releaseShaderCache,
21205 programs: programs,
21211 function WebGLProperties() {
21213 let properties =
new WeakMap();
21215 function get(
object ) {
21217 let map = properties.get(
object );
21222 properties.set(
object, map );
21230 function remove(
object ) {
21232 properties.delete(
object );
21236 function update(
object, key, value ) {
21238 properties.get(
object )[ key ] = value;
21244 properties =
new WeakMap();
21257 function painterSortStable(
a,
b ) {
21259 if (
a.groupOrder !==
b.groupOrder ) {
21261 return a.groupOrder -
b.groupOrder;
21263 }
else if (
a.renderOrder !==
b.renderOrder ) {
21265 return a.renderOrder -
b.renderOrder;
21267 }
else if (
a.material.id !==
b.material.id ) {
21269 return a.material.id -
b.material.id;
21271 }
else if (
a.z !==
b.z ) {
21277 return a.id -
b.id;
21283 function reversePainterSortStable(
a,
b ) {
21285 if (
a.groupOrder !==
b.groupOrder ) {
21287 return a.groupOrder -
b.groupOrder;
21289 }
else if (
a.renderOrder !==
b.renderOrder ) {
21291 return a.renderOrder -
b.renderOrder;
21293 }
else if (
a.z !==
b.z ) {
21299 return a.id -
b.id;
21306 function WebGLRenderList() {
21308 const renderItems = [];
21309 let renderItemsIndex = 0;
21312 const transmissive = [];
21313 const transparent = [];
21317 renderItemsIndex = 0;
21320 transmissive.length = 0;
21321 transparent.length = 0;
21325 function getNextRenderItem(
object, geometry, material, groupOrder,
z, group ) {
21327 let renderItem = renderItems[ renderItemsIndex ];
21334 geometry: geometry,
21335 material: material,
21336 groupOrder: groupOrder,
21337 renderOrder:
object.renderOrder,
21342 renderItems[ renderItemsIndex ] = renderItem;
21346 renderItem.id =
object.id;
21347 renderItem.object =
object;
21348 renderItem.geometry = geometry;
21349 renderItem.material = material;
21350 renderItem.groupOrder = groupOrder;
21351 renderItem.renderOrder =
object.renderOrder;
21353 renderItem.group = group;
21357 renderItemsIndex ++;
21363 function push(
object, geometry, material, groupOrder,
z, group ) {
21365 const renderItem = getNextRenderItem(
object, geometry, material, groupOrder,
z, group );
21367 if ( material.transmission > 0.0 ) {
21369 transmissive.push( renderItem );
21371 }
else if ( material.transparent ===
true ) {
21373 transparent.push( renderItem );
21377 opaque.push( renderItem );
21383 function unshift(
object, geometry, material, groupOrder,
z, group ) {
21385 const renderItem = getNextRenderItem(
object, geometry, material, groupOrder,
z, group );
21387 if ( material.transmission > 0.0 ) {
21389 transmissive.unshift( renderItem );
21391 }
else if ( material.transparent ===
true ) {
21393 transparent.unshift( renderItem );
21397 opaque.unshift( renderItem );
21403 function sort( customOpaqueSort, customTransparentSort ) {
21405 if ( opaque.length > 1 ) opaque.sort( customOpaqueSort || painterSortStable );
21406 if ( transmissive.length > 1 ) transmissive.sort( customTransparentSort || reversePainterSortStable );
21407 if ( transparent.length > 1 ) transparent.sort( customTransparentSort || reversePainterSortStable );
21411 function finish() {
21415 for ( let
i = renderItemsIndex, il = renderItems.length;
i < il;
i ++ ) {
21417 const renderItem = renderItems[
i ];
21419 if ( renderItem.id ===
null )
break;
21421 renderItem.id =
null;
21422 renderItem.object =
null;
21423 renderItem.geometry =
null;
21424 renderItem.material =
null;
21425 renderItem.group =
null;
21434 transmissive: transmissive,
21435 transparent: transparent,
21447 function WebGLRenderLists() {
21449 let lists =
new WeakMap();
21451 function get( scene, renderCallDepth ) {
21453 const listArray = lists.get( scene );
21458 list =
new WebGLRenderList();
21459 lists.set( scene, [ list ] );
21463 if ( renderCallDepth >= listArray.length ) {
21465 list =
new WebGLRenderList();
21466 listArray.push( list );
21470 list = listArray[ renderCallDepth ];
21482 lists =
new WeakMap();
21493 function UniformsCache() {
21499 get:
function ( light ) {
21501 if ( lights[ light.id ] !==
undefined ) {
21503 return lights[ light.id ];
21509 switch ( light.type ) {
21511 case 'DirectionalLight':
21522 color:
new Color(),
21533 color:
new Color(),
21539 case 'HemisphereLight':
21542 skyColor:
new Color(),
21543 groundColor:
new Color()
21547 case 'RectAreaLight':
21549 color:
new Color(),
21558 lights[ light.id ] = uniforms;
21568 function ShadowUniformsCache() {
21574 get:
function ( light ) {
21576 if ( lights[ light.id ] !==
undefined ) {
21578 return lights[ light.id ];
21584 switch ( light.type ) {
21586 case 'DirectionalLight':
21589 shadowNormalBias: 0,
21598 shadowNormalBias: 0,
21607 shadowNormalBias: 0,
21609 shadowMapSize:
new Vector2(),
21610 shadowCameraNear: 1,
21611 shadowCameraFar: 1000
21619 lights[ light.id ] = uniforms;
21631 let nextVersion = 0;
21633 function shadowCastingAndTexturingLightsFirst( lightA, lightB ) {
21635 return ( lightB.castShadow ? 2 : 0 ) - ( lightA.castShadow ? 2 : 0 ) + ( lightB.map ? 1 : 0 ) - ( lightA.map ? 1 : 0 );
21639 function WebGLLights( extensions, capabilities ) {
21641 const cache =
new UniformsCache();
21643 const shadowCache = ShadowUniformsCache();
21650 directionalLength: - 1,
21653 rectAreaLength: - 1,
21656 numDirectionalShadows: - 1,
21657 numPointShadows: - 1,
21658 numSpotShadows: - 1,
21661 numLightProbes: - 1
21664 ambient: [ 0, 0, 0 ],
21667 directionalShadow: [],
21668 directionalShadowMap: [],
21669 directionalShadowMatrix: [],
21674 spotLightMatrix: [],
21676 rectAreaLTC1:
null,
21677 rectAreaLTC2:
null,
21680 pointShadowMap: [],
21681 pointShadowMatrix: [],
21683 numSpotLightShadowsWithMaps: 0,
21688 for ( let
i = 0;
i < 9;
i ++ ) state.probe.push(
new Vector3() );
21690 const vector3 =
new Vector3();
21691 const matrix4 =
new Matrix4();
21692 const matrix42 =
new Matrix4();
21694 function setup( lights, useLegacyLights ) {
21696 let
r = 0,
g = 0,
b = 0;
21698 for ( let
i = 0;
i < 9;
i ++ ) state.probe[
i ].set( 0, 0, 0 );
21700 let directionalLength = 0;
21701 let pointLength = 0;
21702 let spotLength = 0;
21703 let rectAreaLength = 0;
21704 let hemiLength = 0;
21706 let numDirectionalShadows = 0;
21707 let numPointShadows = 0;
21708 let numSpotShadows = 0;
21709 let numSpotMaps = 0;
21710 let numSpotShadowsWithMaps = 0;
21712 let numLightProbes = 0;
21715 lights.sort( shadowCastingAndTexturingLightsFirst );
21718 const scaleFactor = ( useLegacyLights === true ) ?
Math.PI : 1;
21720 for ( let
i = 0,
l = lights.length;
i <
l;
i ++ ) {
21722 const light = lights[
i ];
21724 const color = light.color;
21725 const intensity = light.intensity;
21726 const distance = light.distance;
21728 const shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null;
21730 if ( light.isAmbientLight ) {
21732 r += color.r * intensity * scaleFactor;
21733 g += color.g * intensity * scaleFactor;
21734 b += color.b * intensity * scaleFactor;
21736 }
else if ( light.isLightProbe ) {
21738 for ( let
j = 0;
j < 9;
j ++ ) {
21740 state.probe[
j ].addScaledVector( light.sh.coefficients[
j ], intensity );
21746 }
else if ( light.isDirectionalLight ) {
21748 const uniforms =
cache.get( light );
21750 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor );
21752 if ( light.castShadow ) {
21754 const shadow = light.shadow;
21756 const shadowUniforms = shadowCache.get( light );
21758 shadowUniforms.shadowBias = shadow.bias;
21759 shadowUniforms.shadowNormalBias = shadow.normalBias;
21760 shadowUniforms.shadowRadius = shadow.radius;
21761 shadowUniforms.shadowMapSize = shadow.mapSize;
21763 state.directionalShadow[ directionalLength ] = shadowUniforms;
21764 state.directionalShadowMap[ directionalLength ] = shadowMap;
21765 state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
21767 numDirectionalShadows ++;
21771 state.directional[ directionalLength ] = uniforms;
21773 directionalLength ++;
21775 }
else if ( light.isSpotLight ) {
21777 const uniforms =
cache.get( light );
21779 uniforms.position.setFromMatrixPosition( light.matrixWorld );
21781 uniforms.color.copy( color ).multiplyScalar( intensity * scaleFactor );
21782 uniforms.distance = distance;
21784 uniforms.coneCos =
Math.cos( light.angle );
21785 uniforms.penumbraCos =
Math.cos( light.angle * ( 1 - light.penumbra ) );
21786 uniforms.decay = light.decay;
21788 state.spot[ spotLength ] = uniforms;
21790 const shadow = light.shadow;
21794 state.spotLightMap[ numSpotMaps ] = light.map;
21799 shadow.updateMatrices( light );
21801 if ( light.castShadow ) numSpotShadowsWithMaps ++;
21805 state.spotLightMatrix[ spotLength ] = shadow.matrix;
21807 if ( light.castShadow ) {
21809 const shadowUniforms = shadowCache.get( light );
21811 shadowUniforms.shadowBias = shadow.bias;
21812 shadowUniforms.shadowNormalBias = shadow.normalBias;
21813 shadowUniforms.shadowRadius = shadow.radius;
21814 shadowUniforms.shadowMapSize = shadow.mapSize;
21816 state.spotShadow[ spotLength ] = shadowUniforms;
21817 state.spotShadowMap[ spotLength ] = shadowMap;
21825 }
else if ( light.isRectAreaLight ) {
21827 const uniforms =
cache.get( light );
21829 uniforms.color.copy( color ).multiplyScalar( intensity );
21831 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
21832 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
21834 state.rectArea[ rectAreaLength ] = uniforms;
21838 }
else if ( light.isPointLight ) {
21840 const uniforms =
cache.get( light );
21842 uniforms.color.copy( light.color ).multiplyScalar( light.intensity * scaleFactor );
21843 uniforms.distance = light.distance;
21844 uniforms.decay = light.decay;
21846 if ( light.castShadow ) {
21848 const shadow = light.shadow;
21850 const shadowUniforms = shadowCache.get( light );
21852 shadowUniforms.shadowBias = shadow.bias;
21853 shadowUniforms.shadowNormalBias = shadow.normalBias;
21854 shadowUniforms.shadowRadius = shadow.radius;
21855 shadowUniforms.shadowMapSize = shadow.mapSize;
21856 shadowUniforms.shadowCameraNear = shadow.camera.near;
21857 shadowUniforms.shadowCameraFar = shadow.camera.far;
21859 state.pointShadow[ pointLength ] = shadowUniforms;
21860 state.pointShadowMap[ pointLength ] = shadowMap;
21861 state.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
21863 numPointShadows ++;
21867 state.point[ pointLength ] = uniforms;
21871 }
else if ( light.isHemisphereLight ) {
21873 const uniforms =
cache.get( light );
21875 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity * scaleFactor );
21876 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity * scaleFactor );
21878 state.hemi[ hemiLength ] = uniforms;
21886 if ( rectAreaLength > 0 ) {
21888 if ( capabilities.isWebGL2 ) {
21892 if ( extensions.has(
'OES_texture_float_linear' ) ===
true ) {
21908 if ( extensions.has(
'OES_texture_float_linear' ) ===
true ) {
21913 }
else if ( extensions.has(
'OES_texture_half_float_linear' ) ===
true ) {
21920 console.error(
'THREE.WebGLRenderer: Unable to use RectAreaLight. Missing WebGL extensions.' );
21928 state.ambient[ 0 ] =
r;
21929 state.ambient[ 1 ] =
g;
21930 state.ambient[ 2 ] =
b;
21932 const hash = state.hash;
21934 if ( hash.directionalLength !== directionalLength ||
21935 hash.pointLength !== pointLength ||
21936 hash.spotLength !== spotLength ||
21937 hash.rectAreaLength !== rectAreaLength ||
21938 hash.hemiLength !== hemiLength ||
21939 hash.numDirectionalShadows !== numDirectionalShadows ||
21940 hash.numPointShadows !== numPointShadows ||
21941 hash.numSpotShadows !== numSpotShadows ||
21942 hash.numSpotMaps !== numSpotMaps ||
21943 hash.numLightProbes !== numLightProbes ) {
21945 state.directional.length = directionalLength;
21946 state.spot.length = spotLength;
21947 state.rectArea.length = rectAreaLength;
21948 state.point.length = pointLength;
21949 state.hemi.length = hemiLength;
21951 state.directionalShadow.length = numDirectionalShadows;
21952 state.directionalShadowMap.length = numDirectionalShadows;
21953 state.pointShadow.length = numPointShadows;
21954 state.pointShadowMap.length = numPointShadows;
21955 state.spotShadow.length = numSpotShadows;
21956 state.spotShadowMap.length = numSpotShadows;
21957 state.directionalShadowMatrix.length = numDirectionalShadows;
21958 state.pointShadowMatrix.length = numPointShadows;
21959 state.spotLightMatrix.length = numSpotShadows + numSpotMaps - numSpotShadowsWithMaps;
21960 state.spotLightMap.length = numSpotMaps;
21961 state.numSpotLightShadowsWithMaps = numSpotShadowsWithMaps;
21962 state.numLightProbes = numLightProbes;
21964 hash.directionalLength = directionalLength;
21965 hash.pointLength = pointLength;
21966 hash.spotLength = spotLength;
21967 hash.rectAreaLength = rectAreaLength;
21968 hash.hemiLength = hemiLength;
21970 hash.numDirectionalShadows = numDirectionalShadows;
21971 hash.numPointShadows = numPointShadows;
21972 hash.numSpotShadows = numSpotShadows;
21973 hash.numSpotMaps = numSpotMaps;
21975 hash.numLightProbes = numLightProbes;
21977 state.version = nextVersion ++;
21983 function setupView( lights, camera ) {
21985 let directionalLength = 0;
21986 let pointLength = 0;
21987 let spotLength = 0;
21988 let rectAreaLength = 0;
21989 let hemiLength = 0;
21991 const viewMatrix = camera.matrixWorldInverse;
21993 for ( let
i = 0,
l = lights.length;
i <
l;
i ++ ) {
21995 const light = lights[
i ];
21997 if ( light.isDirectionalLight ) {
21999 const uniforms = state.directional[ directionalLength ];
22001 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22002 vector3.setFromMatrixPosition( light.target.matrixWorld );
22003 uniforms.direction.sub( vector3 );
22004 uniforms.direction.transformDirection( viewMatrix );
22006 directionalLength ++;
22008 }
else if ( light.isSpotLight ) {
22010 const uniforms = state.spot[ spotLength ];
22012 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22013 uniforms.position.applyMatrix4( viewMatrix );
22015 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22016 vector3.setFromMatrixPosition( light.target.matrixWorld );
22017 uniforms.direction.sub( vector3 );
22018 uniforms.direction.transformDirection( viewMatrix );
22022 }
else if ( light.isRectAreaLight ) {
22024 const uniforms = state.rectArea[ rectAreaLength ];
22026 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22027 uniforms.position.applyMatrix4( viewMatrix );
22030 matrix42.identity();
22031 matrix4.copy( light.matrixWorld );
22032 matrix4.premultiply( viewMatrix );
22033 matrix42.extractRotation( matrix4 );
22035 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 );
22036 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 );
22038 uniforms.halfWidth.applyMatrix4( matrix42 );
22039 uniforms.halfHeight.applyMatrix4( matrix42 );
22043 }
else if ( light.isPointLight ) {
22045 const uniforms = state.point[ pointLength ];
22047 uniforms.position.setFromMatrixPosition( light.matrixWorld );
22048 uniforms.position.applyMatrix4( viewMatrix );
22052 }
else if ( light.isHemisphereLight ) {
22054 const uniforms = state.hemi[ hemiLength ];
22056 uniforms.direction.setFromMatrixPosition( light.matrixWorld );
22057 uniforms.direction.transformDirection( viewMatrix );
22069 setupView: setupView,
22075 function WebGLRenderState( extensions, capabilities ) {
22077 const lights =
new WebGLLights( extensions, capabilities );
22079 const lightsArray = [];
22080 const shadowsArray = [];
22084 lightsArray.length = 0;
22085 shadowsArray.length = 0;
22089 function pushLight( light ) {
22091 lightsArray.push( light );
22095 function pushShadow( shadowLight ) {
22097 shadowsArray.push( shadowLight );
22101 function setupLights( useLegacyLights ) {
22103 lights.setup( lightsArray, useLegacyLights );
22107 function setupLightsView( camera ) {
22109 lights.setupView( lightsArray, camera );
22114 lightsArray: lightsArray,
22115 shadowsArray: shadowsArray,
22123 setupLights: setupLights,
22124 setupLightsView: setupLightsView,
22126 pushLight: pushLight,
22127 pushShadow: pushShadow
22132 function WebGLRenderStates( extensions, capabilities ) {
22134 let renderStates =
new WeakMap();
22136 function get( scene, renderCallDepth = 0 ) {
22138 const renderStateArray = renderStates.get( scene );
22141 if ( renderStateArray ===
undefined ) {
22143 renderState =
new WebGLRenderState( extensions, capabilities );
22144 renderStates.set( scene, [ renderState ] );
22148 if ( renderCallDepth >= renderStateArray.length ) {
22150 renderState =
new WebGLRenderState( extensions, capabilities );
22151 renderStateArray.push( renderState );
22155 renderState = renderStateArray[ renderCallDepth ];
22161 return renderState;
22167 renderStates =
new WeakMap();
22180 constructor( parameters ) {
22184 this.isMeshDepthMaterial =
true;
22186 this.type =
'MeshDepthMaterial';
22188 this.depthPacking = BasicDepthPacking;
22192 this.alphaMap =
null;
22194 this.displacementMap =
null;
22195 this.displacementScale = 1;
22196 this.displacementBias = 0;
22198 this.wireframe =
false;
22199 this.wireframeLinewidth = 1;
22201 this.setValues( parameters );
22207 super.copy( source );
22209 this.depthPacking = source.depthPacking;
22211 this.map = source.map;
22213 this.alphaMap = source.alphaMap;
22215 this.displacementMap = source.displacementMap;
22216 this.displacementScale = source.displacementScale;
22217 this.displacementBias = source.displacementBias;
22219 this.wireframe = source.wireframe;
22220 this.wireframeLinewidth = source.wireframeLinewidth;
22228 class MeshDistanceMaterial
extends Material {
22230 constructor( parameters ) {
22234 this.isMeshDistanceMaterial =
true;
22236 this.type =
'MeshDistanceMaterial';
22240 this.alphaMap =
null;
22242 this.displacementMap =
null;
22243 this.displacementScale = 1;
22244 this.displacementBias = 0;
22246 this.setValues( parameters );
22252 super.copy( source );
22254 this.map = source.map;
22256 this.alphaMap = source.alphaMap;
22258 this.displacementMap = source.displacementMap;
22259 this.displacementScale = source.displacementScale;
22260 this.displacementBias = source.displacementBias;
22268 const vertex =
"void main() {\n\tgl_Position = vec4( position, 1.0 );\n}";
22270 const fragment =
"uniform sampler2D shadow_pass;\nuniform vec2 resolution;\nuniform float radius;\n#include <packing>\nvoid main() {\n\tconst float samples = float( VSM_SAMPLES );\n\tfloat mean = 0.0;\n\tfloat squared_mean = 0.0;\n\tfloat uvStride = samples <= 1.0 ? 0.0 : 2.0 / ( samples - 1.0 );\n\tfloat uvStart = samples <= 1.0 ? 0.0 : - 1.0;\n\tfor ( float i = 0.0; i < samples; i ++ ) {\n\t\tfloat uvOffset = uvStart + i * uvStride;\n\t\t#ifdef HORIZONTAL_PASS\n\t\t\tvec2 distribution = unpackRGBATo2Half( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( uvOffset, 0.0 ) * radius ) / resolution ) );\n\t\t\tmean += distribution.x;\n\t\t\tsquared_mean += distribution.y * distribution.y + distribution.x * distribution.x;\n\t\t#else\n\t\t\tfloat depth = unpackRGBAToDepth( texture2D( shadow_pass, ( gl_FragCoord.xy + vec2( 0.0, uvOffset ) * radius ) / resolution ) );\n\t\t\tmean += depth;\n\t\t\tsquared_mean += depth * depth;\n\t\t#endif\n\t}\n\tmean = mean / samples;\n\tsquared_mean = squared_mean / samples;\n\tfloat std_dev = sqrt( squared_mean - mean * mean );\n\tgl_FragColor = pack2HalfToRGBA( vec2( mean, std_dev ) );\n}";
22272 function WebGLShadowMap( _renderer, _objects, _capabilities ) {
22274 let _frustum =
new Frustum();
22276 const _shadowMapSize =
new Vector2(),
22277 _viewportSize =
new Vector2(),
22282 _distanceMaterial =
new MeshDistanceMaterial(),
22284 _materialCache = {},
22286 _maxTextureSize = _capabilities.maxTextureSize;
22295 shadow_pass: { value:
null },
22296 resolution: { value:
new Vector2() },
22297 radius: { value: 4.0 }
22300 vertexShader: vertex,
22301 fragmentShader: fragment
22305 const shadowMaterialHorizontal = shadowMaterialVertical.clone();
22306 shadowMaterialHorizontal.defines.HORIZONTAL_PASS = 1;
22309 fullScreenTri.setAttribute(
22312 new Float32Array( [ - 1, - 1, 0.5, 3, - 1, 0.5, - 1, 3, 0.5 ] ),
22317 const fullScreenMesh =
new Mesh( fullScreenTri, shadowMaterialVertical );
22319 const scope =
this;
22321 this.enabled =
false;
22323 this.autoUpdate =
true;
22324 this.needsUpdate =
false;
22327 let _previousType = this.type;
22329 this.render =
function ( lights, scene, camera ) {
22331 if ( scope.enabled ===
false )
return;
22332 if ( scope.autoUpdate ===
false && scope.needsUpdate ===
false )
return;
22334 if ( lights.length === 0 )
return;
22336 const currentRenderTarget = _renderer.getRenderTarget();
22337 const activeCubeFace = _renderer.getActiveCubeFace();
22338 const activeMipmapLevel = _renderer.getActiveMipmapLevel();
22340 const _state = _renderer.state;
22344 _state.buffers.color.setClear( 1, 1, 1, 1 );
22345 _state.buffers.depth.setTest(
true );
22346 _state.setScissorTest(
false );
22350 const toVSM = ( _previousType !== VSMShadowMap && this.type === VSMShadowMap );
22351 const fromVSM = ( _previousType === VSMShadowMap && this.type !== VSMShadowMap );
22355 for ( let
i = 0, il = lights.length;
i < il;
i ++ ) {
22357 const light = lights[
i ];
22358 const shadow = light.shadow;
22362 console.warn(
'THREE.WebGLShadowMap:', light,
'has no shadow.' );
22367 if ( shadow.autoUpdate ===
false && shadow.needsUpdate ===
false )
continue;
22369 _shadowMapSize.copy( shadow.mapSize );
22371 const shadowFrameExtents = shadow.getFrameExtents();
22373 _shadowMapSize.multiply( shadowFrameExtents );
22375 _viewportSize.copy( shadow.mapSize );
22377 if ( _shadowMapSize.x > _maxTextureSize || _shadowMapSize.y > _maxTextureSize ) {
22379 if ( _shadowMapSize.x > _maxTextureSize ) {
22381 _viewportSize.x =
Math.floor( _maxTextureSize / shadowFrameExtents.x );
22382 _shadowMapSize.x = _viewportSize.x * shadowFrameExtents.x;
22383 shadow.mapSize.x = _viewportSize.x;
22387 if ( _shadowMapSize.y > _maxTextureSize ) {
22389 _viewportSize.y =
Math.floor( _maxTextureSize / shadowFrameExtents.y );
22390 _shadowMapSize.y = _viewportSize.y * shadowFrameExtents.y;
22391 shadow.mapSize.y = _viewportSize.y;
22397 if ( shadow.map ===
null || toVSM ===
true || fromVSM ===
true ) {
22401 if ( shadow.map !==
null ) {
22403 shadow.map.dispose();
22407 shadow.map =
new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars );
22408 shadow.map.texture.name = light.name +
'.shadowMap';
22410 shadow.camera.updateProjectionMatrix();
22414 _renderer.setRenderTarget( shadow.map );
22417 const viewportCount = shadow.getViewportCount();
22419 for ( let vp = 0; vp < viewportCount; vp ++ ) {
22421 const viewport = shadow.getViewport( vp );
22424 _viewportSize.x * viewport.x,
22425 _viewportSize.y * viewport.y,
22426 _viewportSize.x * viewport.z,
22427 _viewportSize.y * viewport.w
22430 _state.viewport( _viewport );
22432 shadow.updateMatrices( light, vp );
22434 _frustum = shadow.getFrustum();
22436 renderObject( scene, camera, shadow.camera, light,
this.type );
22442 if ( shadow.isPointLightShadow !==
true &&
this.type === VSMShadowMap ) {
22444 VSMPass( shadow, camera );
22448 shadow.needsUpdate =
false;
22452 _previousType = this.type;
22454 scope.needsUpdate =
false;
22456 _renderer.setRenderTarget( currentRenderTarget, activeCubeFace, activeMipmapLevel );
22460 function VSMPass( shadow, camera ) {
22462 const geometry = _objects.update( fullScreenMesh );
22464 if ( shadowMaterialVertical.defines.VSM_SAMPLES !== shadow.blurSamples ) {
22466 shadowMaterialVertical.defines.VSM_SAMPLES = shadow.blurSamples;
22467 shadowMaterialHorizontal.defines.VSM_SAMPLES = shadow.blurSamples;
22469 shadowMaterialVertical.needsUpdate =
true;
22470 shadowMaterialHorizontal.needsUpdate =
true;
22474 if ( shadow.mapPass ===
null ) {
22482 shadowMaterialVertical.uniforms.shadow_pass.value = shadow.map.texture;
22483 shadowMaterialVertical.uniforms.resolution.value = shadow.mapSize;
22484 shadowMaterialVertical.uniforms.radius.value = shadow.radius;
22485 _renderer.setRenderTarget( shadow.mapPass );
22487 _renderer.renderBufferDirect( camera,
null, geometry, shadowMaterialVertical, fullScreenMesh,
null );
22491 shadowMaterialHorizontal.uniforms.shadow_pass.value = shadow.mapPass.texture;
22492 shadowMaterialHorizontal.uniforms.resolution.value = shadow.mapSize;
22493 shadowMaterialHorizontal.uniforms.radius.value = shadow.radius;
22494 _renderer.setRenderTarget( shadow.map );
22496 _renderer.renderBufferDirect( camera,
null, geometry, shadowMaterialHorizontal, fullScreenMesh,
null );
22500 function getDepthMaterial(
object, material, light, type ) {
22504 const customMaterial = ( light.isPointLight === true ) ?
object.customDistanceMaterial :
object.customDepthMaterial;
22508 result = customMaterial;
22512 result = ( light.isPointLight === true ) ? _distanceMaterial : _depthMaterial;
22514 if ( ( _renderer.localClippingEnabled && material.clipShadows ===
true &&
Array.isArray( material.clippingPlanes ) && material.clippingPlanes.length !== 0 ) ||
22515 ( material.displacementMap && material.displacementScale !== 0 ) ||
22516 ( material.alphaMap && material.alphaTest > 0 ) ||
22517 ( material.map && material.alphaTest > 0 ) ) {
22522 const keyA = result.uuid, keyB = material.uuid;
22524 let materialsForVariant = _materialCache[ keyA ];
22526 if ( materialsForVariant ===
undefined ) {
22528 materialsForVariant = {};
22529 _materialCache[ keyA ] = materialsForVariant;
22533 let cachedMaterial = materialsForVariant[ keyB ];
22537 cachedMaterial = result.clone();
22538 materialsForVariant[ keyB ] = cachedMaterial;
22539 material.addEventListener(
'dispose', onMaterialDispose );
22543 result = cachedMaterial;
22549 result.visible = material.visible;
22550 result.wireframe = material.wireframe;
22552 if ( type === VSMShadowMap ) {
22554 result.side = ( material.shadowSide !== null ) ? material.shadowSide : material.side;
22558 result.side = ( material.shadowSide !== null ) ? material.shadowSide : shadowSide[ material.side ];
22562 result.alphaMap = material.alphaMap;
22563 result.alphaTest = material.alphaTest;
22564 result.map = material.map;
22566 result.clipShadows = material.clipShadows;
22567 result.clippingPlanes = material.clippingPlanes;
22568 result.clipIntersection = material.clipIntersection;
22570 result.displacementMap = material.displacementMap;
22571 result.displacementScale = material.displacementScale;
22572 result.displacementBias = material.displacementBias;
22574 result.wireframeLinewidth = material.wireframeLinewidth;
22575 result.linewidth = material.linewidth;
22577 if ( light.isPointLight ===
true && result.isMeshDistanceMaterial ===
true ) {
22579 const materialProperties = _renderer.properties.get( result );
22580 materialProperties.light = light;
22588 function renderObject(
object, camera, shadowCamera, light, type ) {
22590 if (
object.visible ===
false )
return;
22592 const visible =
object.layers.test( camera.layers );
22594 if ( visible && (
object.isMesh ||
object.isLine ||
object.isPoints ) ) {
22596 if ( (
object.castShadow || (
object.receiveShadow && type === VSMShadowMap ) ) && ( !
object.frustumCulled || _frustum.intersectsObject(
object ) ) ) {
22598 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse,
object.matrixWorld );
22600 const geometry = _objects.update(
object );
22601 const material =
object.material;
22603 if (
Array.isArray( material ) ) {
22605 const groups = geometry.groups;
22607 for ( let
k = 0, kl = groups.length;
k < kl;
k ++ ) {
22609 const group = groups[
k ];
22610 const groupMaterial = material[ group.materialIndex ];
22612 if ( groupMaterial && groupMaterial.visible ) {
22614 const depthMaterial = getDepthMaterial(
object, groupMaterial, light, type );
22616 object.onBeforeShadow( _renderer,
object, camera, shadowCamera, geometry, depthMaterial, group );
22618 _renderer.renderBufferDirect( shadowCamera,
null, geometry, depthMaterial,
object, group );
22620 object.onAfterShadow( _renderer,
object, camera, shadowCamera, geometry, depthMaterial, group );
22626 }
else if ( material.visible ) {
22628 const depthMaterial = getDepthMaterial(
object, material, light, type );
22630 object.onBeforeShadow( _renderer,
object, camera, shadowCamera, geometry, depthMaterial,
null );
22632 _renderer.renderBufferDirect( shadowCamera,
null, geometry, depthMaterial,
object,
null );
22634 object.onAfterShadow( _renderer,
object, camera, shadowCamera, geometry, depthMaterial,
null );
22642 const children =
object.children;
22644 for ( let
i = 0,
l = children.length;
i <
l;
i ++ ) {
22646 renderObject( children[
i ], camera, shadowCamera, light, type );
22652 function onMaterialDispose( event ) {
22654 const material =
event.target;
22656 material.removeEventListener(
'dispose', onMaterialDispose );
22660 for (
const id in _materialCache ) {
22662 const cache = _materialCache[ id ];
22664 const uuid =
event.target.uuid;
22666 if ( uuid in
cache ) {
22668 const shadowMaterial =
cache[ uuid ];
22669 shadowMaterial.dispose();
22670 delete cache[ uuid ];
22680 function WebGLState( gl, extensions, capabilities ) {
22682 const isWebGL2 = capabilities.isWebGL2;
22684 function ColorBuffer() {
22686 let locked =
false;
22689 let currentColorMask =
null;
22690 const currentColorClear =
new Vector4( 0, 0, 0, 0 );
22694 setMask:
function ( colorMask ) {
22696 if ( currentColorMask !== colorMask && ! locked ) {
22698 gl.colorMask( colorMask, colorMask, colorMask, colorMask );
22699 currentColorMask = colorMask;
22705 setLocked:
function ( lock ) {
22711 setClear:
function (
r,
g,
b,
a, premultipliedAlpha ) {
22713 if ( premultipliedAlpha ===
true ) {
22719 color.set(
r,
g,
b,
a );
22721 if ( currentColorClear.equals( color ) ===
false ) {
22723 gl.clearColor(
r,
g,
b,
a );
22724 currentColorClear.copy( color );
22730 reset:
function () {
22734 currentColorMask =
null;
22735 currentColorClear.set( - 1, 0, 0, 0 );
22743 function DepthBuffer() {
22745 let locked =
false;
22747 let currentDepthMask =
null;
22748 let currentDepthFunc =
null;
22749 let currentDepthClear =
null;
22753 setTest:
function ( depthTest ) {
22757 enable( gl.DEPTH_TEST );
22761 disable( gl.DEPTH_TEST );
22767 setMask:
function ( depthMask ) {
22769 if ( currentDepthMask !== depthMask && ! locked ) {
22771 gl.depthMask( depthMask );
22772 currentDepthMask = depthMask;
22778 setFunc:
function ( depthFunc ) {
22780 if ( currentDepthFunc !== depthFunc ) {
22782 switch ( depthFunc ) {
22786 gl.depthFunc( gl.NEVER );
22791 gl.depthFunc( gl.ALWAYS );
22796 gl.depthFunc( gl.LESS );
22799 case LessEqualDepth:
22801 gl.depthFunc( gl.LEQUAL );
22806 gl.depthFunc( gl.EQUAL );
22809 case GreaterEqualDepth:
22811 gl.depthFunc( gl.GEQUAL );
22816 gl.depthFunc( gl.GREATER );
22819 case NotEqualDepth:
22821 gl.depthFunc( gl.NOTEQUAL );
22826 gl.depthFunc( gl.LEQUAL );
22830 currentDepthFunc = depthFunc;
22836 setLocked:
function ( lock ) {
22842 setClear:
function ( depth ) {
22844 if ( currentDepthClear !== depth ) {
22846 gl.clearDepth( depth );
22847 currentDepthClear = depth;
22853 reset:
function () {
22857 currentDepthMask =
null;
22858 currentDepthFunc =
null;
22859 currentDepthClear =
null;
22867 function StencilBuffer() {
22869 let locked =
false;
22871 let currentStencilMask =
null;
22872 let currentStencilFunc =
null;
22873 let currentStencilRef =
null;
22874 let currentStencilFuncMask =
null;
22875 let currentStencilFail =
null;
22876 let currentStencilZFail =
null;
22877 let currentStencilZPass =
null;
22878 let currentStencilClear =
null;
22882 setTest:
function ( stencilTest ) {
22886 if ( stencilTest ) {
22888 enable( gl.STENCIL_TEST );
22892 disable( gl.STENCIL_TEST );
22900 setMask:
function ( stencilMask ) {
22902 if ( currentStencilMask !== stencilMask && ! locked ) {
22904 gl.stencilMask( stencilMask );
22905 currentStencilMask = stencilMask;
22911 setFunc:
function ( stencilFunc, stencilRef, stencilMask ) {
22913 if ( currentStencilFunc !== stencilFunc ||
22914 currentStencilRef !== stencilRef ||
22915 currentStencilFuncMask !== stencilMask ) {
22917 gl.stencilFunc( stencilFunc, stencilRef, stencilMask );
22919 currentStencilFunc = stencilFunc;
22920 currentStencilRef = stencilRef;
22921 currentStencilFuncMask = stencilMask;
22927 setOp:
function ( stencilFail, stencilZFail, stencilZPass ) {
22929 if ( currentStencilFail !== stencilFail ||
22930 currentStencilZFail !== stencilZFail ||
22931 currentStencilZPass !== stencilZPass ) {
22933 gl.stencilOp( stencilFail, stencilZFail, stencilZPass );
22935 currentStencilFail = stencilFail;
22936 currentStencilZFail = stencilZFail;
22937 currentStencilZPass = stencilZPass;
22943 setLocked:
function ( lock ) {
22949 setClear:
function ( stencil ) {
22951 if ( currentStencilClear !== stencil ) {
22953 gl.clearStencil( stencil );
22954 currentStencilClear = stencil;
22960 reset:
function () {
22964 currentStencilMask =
null;
22965 currentStencilFunc =
null;
22966 currentStencilRef =
null;
22967 currentStencilFuncMask =
null;
22968 currentStencilFail =
null;
22969 currentStencilZFail =
null;
22970 currentStencilZPass =
null;
22971 currentStencilClear =
null;
22981 const colorBuffer =
new ColorBuffer();
22982 const depthBuffer =
new DepthBuffer();
22983 const stencilBuffer =
new StencilBuffer();
22985 const uboBindings =
new WeakMap();
22986 const uboProgramMap =
new WeakMap();
22988 let enabledCapabilities = {};
22990 let currentBoundFramebuffers = {};
22991 let currentDrawbuffers =
new WeakMap();
22992 let defaultDrawbuffers = [];
22994 let currentProgram =
null;
22996 let currentBlendingEnabled =
false;
22997 let currentBlending =
null;
22998 let currentBlendEquation =
null;
22999 let currentBlendSrc =
null;
23000 let currentBlendDst =
null;
23001 let currentBlendEquationAlpha =
null;
23002 let currentBlendSrcAlpha =
null;
23003 let currentBlendDstAlpha =
null;
23004 let currentBlendColor =
new Color( 0, 0, 0 );
23005 let currentBlendAlpha = 0;
23006 let currentPremultipledAlpha =
false;
23008 let currentFlipSided =
null;
23009 let currentCullFace =
null;
23011 let currentLineWidth =
null;
23013 let currentPolygonOffsetFactor =
null;
23014 let currentPolygonOffsetUnits =
null;
23016 const maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS );
23018 let lineWidthAvailable =
false;
23020 const glVersion = gl.getParameter( gl.VERSION );
23022 if ( glVersion.indexOf(
'WebGL' ) !== - 1 ) {
23024 version = parseFloat( /^WebGL (\
d)/.exec( glVersion )[ 1 ] );
23025 lineWidthAvailable = (
version >= 1.0 );
23027 }
else if ( glVersion.indexOf(
'OpenGL ES' ) !== - 1 ) {
23029 version = parseFloat( /^OpenGL ES (\
d)/.exec( glVersion )[ 1 ] );
23030 lineWidthAvailable = (
version >= 2.0 );
23034 let currentTextureSlot =
null;
23035 let currentBoundTextures = {};
23037 const scissorParam = gl.getParameter( gl.SCISSOR_BOX );
23038 const viewportParam = gl.getParameter( gl.VIEWPORT );
23040 const currentScissor =
new Vector4().fromArray( scissorParam );
23041 const currentViewport =
new Vector4().fromArray( viewportParam );
23043 function createTexture( type, target, count, dimensions ) {
23046 const texture = gl.createTexture();
23048 gl.bindTexture( type, texture );
23049 gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
23050 gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
23052 for ( let
i = 0;
i < count;
i ++ ) {
23054 if ( isWebGL2 && ( type === gl.TEXTURE_3D || type === gl.TEXTURE_2D_ARRAY ) ) {
23056 gl.texImage3D( target, 0, gl.RGBA, 1, 1, dimensions, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
23060 gl.texImage2D( target +
i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data );
23070 const emptyTextures = {};
23071 emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 );
23072 emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 );
23076 emptyTextures[ gl.TEXTURE_2D_ARRAY ] = createTexture( gl.TEXTURE_2D_ARRAY, gl.TEXTURE_2D_ARRAY, 1, 1 );
23077 emptyTextures[ gl.TEXTURE_3D ] = createTexture( gl.TEXTURE_3D, gl.TEXTURE_3D, 1, 1 );
23083 colorBuffer.setClear( 0, 0, 0, 1 );
23084 depthBuffer.setClear( 1 );
23085 stencilBuffer.setClear( 0 );
23087 enable( gl.DEPTH_TEST );
23088 depthBuffer.setFunc( LessEqualDepth );
23090 setFlipSided(
false );
23092 enable( gl.CULL_FACE );
23098 function enable(
id ) {
23100 if ( enabledCapabilities[
id ] !==
true ) {
23103 enabledCapabilities[ id ] =
true;
23109 function disable(
id ) {
23111 if ( enabledCapabilities[
id ] !==
false ) {
23114 enabledCapabilities[ id ] =
false;
23120 function bindFramebuffer( target, framebuffer ) {
23122 if ( currentBoundFramebuffers[ target ] !== framebuffer ) {
23124 gl.bindFramebuffer( target, framebuffer );
23126 currentBoundFramebuffers[ target ] = framebuffer;
23132 if ( target === gl.DRAW_FRAMEBUFFER ) {
23134 currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer;
23138 if ( target === gl.FRAMEBUFFER ) {
23140 currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer;
23154 function drawBuffers( renderTarget, framebuffer ) {
23156 let drawBuffers = defaultDrawbuffers;
23158 let needsUpdate =
false;
23160 if ( renderTarget ) {
23162 drawBuffers = currentDrawbuffers.get( framebuffer );
23167 currentDrawbuffers.set( framebuffer, drawBuffers );
23171 if ( renderTarget.isWebGLMultipleRenderTargets ) {
23173 const textures = renderTarget.texture;
23175 if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) {
23177 for ( let
i = 0, il = textures.length;
i < il;
i ++ ) {
23179 drawBuffers[
i ] = gl.COLOR_ATTACHMENT0 +
i;
23183 drawBuffers.length = textures.length;
23185 needsUpdate =
true;
23191 if ( drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) {
23193 drawBuffers[ 0 ] = gl.COLOR_ATTACHMENT0;
23195 needsUpdate =
true;
23203 if ( drawBuffers[ 0 ] !== gl.BACK ) {
23205 drawBuffers[ 0 ] = gl.BACK;
23207 needsUpdate =
true;
23213 if ( needsUpdate ) {
23215 if ( capabilities.isWebGL2 ) {
23217 gl.drawBuffers( drawBuffers );
23221 extensions.get(
'WEBGL_draw_buffers' ).drawBuffersWEBGL( drawBuffers );
23230 function useProgram( program ) {
23232 if ( currentProgram !== program ) {
23234 gl.useProgram( program );
23236 currentProgram = program;
23246 const equationToGL = {
23254 equationToGL[ MinEquation ] = gl.MIN;
23255 equationToGL[ MaxEquation ] = gl.MAX;
23259 const extension = extensions.get(
'EXT_blend_minmax' );
23261 if ( extension !==
null ) {
23263 equationToGL[ MinEquation ] = extension.MIN_EXT;
23264 equationToGL[ MaxEquation ] = extension.MAX_EXT;
23270 const factorToGL = {
23282 [ ConstantColorFactor ]: gl.CONSTANT_COLOR,
23283 [ OneMinusConstantColorFactor ]: gl.ONE_MINUS_CONSTANT_COLOR,
23284 [ ConstantAlphaFactor ]: gl.CONSTANT_ALPHA,
23285 [ OneMinusConstantAlphaFactor ]: gl.ONE_MINUS_CONSTANT_ALPHA
23288 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, blendColor, blendAlpha, premultipliedAlpha ) {
23292 if ( currentBlendingEnabled ===
true ) {
23294 disable( gl.BLEND );
23295 currentBlendingEnabled =
false;
23303 if ( currentBlendingEnabled ===
false ) {
23305 enable( gl.BLEND );
23306 currentBlendingEnabled =
true;
23312 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) {
23316 gl.blendEquation( gl.FUNC_ADD );
23323 if ( premultipliedAlpha ) {
23325 switch ( blending ) {
23328 gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
23332 gl.blendFunc( gl.ONE, gl.ONE );
23336 gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE );
23340 gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA );
23344 console.error(
'THREE.WebGLState: Invalid blending: ', blending );
23351 switch ( blending ) {
23354 gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA );
23358 gl.blendFunc( gl.SRC_ALPHA, gl.ONE );
23362 gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE );
23366 gl.blendFunc( gl.ZERO, gl.SRC_COLOR );
23370 console.error(
'THREE.WebGLState: Invalid blending: ', blending );
23377 currentBlendSrc =
null;
23378 currentBlendDst =
null;
23379 currentBlendSrcAlpha =
null;
23380 currentBlendDstAlpha =
null;
23381 currentBlendColor.set( 0, 0, 0 );
23382 currentBlendAlpha = 0;
23384 currentBlending = blending;
23385 currentPremultipledAlpha = premultipliedAlpha;
23395 blendEquationAlpha = blendEquationAlpha || blendEquation;
23396 blendSrcAlpha = blendSrcAlpha || blendSrc;
23397 blendDstAlpha = blendDstAlpha || blendDst;
23399 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) {
23401 gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] );
23403 currentBlendEquation = blendEquation;
23404 currentBlendEquationAlpha = blendEquationAlpha;
23408 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) {
23410 gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] );
23412 currentBlendSrc = blendSrc;
23413 currentBlendDst = blendDst;
23414 currentBlendSrcAlpha = blendSrcAlpha;
23415 currentBlendDstAlpha = blendDstAlpha;
23419 if ( blendColor.equals( currentBlendColor ) ===
false || blendAlpha !== currentBlendAlpha ) {
23421 gl.blendColor( blendColor.r, blendColor.g, blendColor.b, blendAlpha );
23423 currentBlendColor.copy( blendColor );
23424 currentBlendAlpha = blendAlpha;
23428 currentBlending = blending;
23429 currentPremultipledAlpha =
false;
23433 function setMaterial( material, frontFaceCW ) {
23436 ? disable( gl.CULL_FACE )
23437 : enable( gl.CULL_FACE );
23439 let flipSided = ( material.side ===
BackSide );
23440 if ( frontFaceCW ) flipSided = ! flipSided;
23442 setFlipSided( flipSided );
23444 ( material.blending ===
NormalBlending && material.transparent === false )
23446 : setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.blendColor, material.blendAlpha, material.premultipliedAlpha );
23448 depthBuffer.setFunc( material.depthFunc );
23449 depthBuffer.setTest( material.depthTest );
23450 depthBuffer.setMask( material.depthWrite );
23451 colorBuffer.setMask( material.colorWrite );
23453 const stencilWrite = material.stencilWrite;
23454 stencilBuffer.setTest( stencilWrite );
23455 if ( stencilWrite ) {
23457 stencilBuffer.setMask( material.stencilWriteMask );
23458 stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
23459 stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
23463 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
23465 material.alphaToCoverage ===
true
23466 ? enable( gl.SAMPLE_ALPHA_TO_COVERAGE )
23467 : disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
23473 function setFlipSided( flipSided ) {
23475 if ( currentFlipSided !== flipSided ) {
23479 gl.frontFace( gl.CW );
23483 gl.frontFace( gl.CCW );
23487 currentFlipSided = flipSided;
23493 function setCullFace( cullFace ) {
23497 enable( gl.CULL_FACE );
23499 if ( cullFace !== currentCullFace ) {
23503 gl.cullFace( gl.BACK );
23507 gl.cullFace( gl.FRONT );
23511 gl.cullFace( gl.FRONT_AND_BACK );
23519 disable( gl.CULL_FACE );
23523 currentCullFace = cullFace;
23527 function setLineWidth( width ) {
23529 if ( width !== currentLineWidth ) {
23531 if ( lineWidthAvailable ) gl.lineWidth( width );
23533 currentLineWidth = width;
23539 function setPolygonOffset( polygonOffset, factor, units ) {
23541 if ( polygonOffset ) {
23543 enable( gl.POLYGON_OFFSET_FILL );
23545 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) {
23547 gl.polygonOffset( factor, units );
23549 currentPolygonOffsetFactor = factor;
23550 currentPolygonOffsetUnits = units;
23556 disable( gl.POLYGON_OFFSET_FILL );
23562 function setScissorTest( scissorTest ) {
23564 if ( scissorTest ) {
23566 enable( gl.SCISSOR_TEST );
23570 disable( gl.SCISSOR_TEST );
23578 function activeTexture( webglSlot ) {
23580 if ( webglSlot ===
undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1;
23582 if ( currentTextureSlot !== webglSlot ) {
23584 gl.activeTexture( webglSlot );
23585 currentTextureSlot = webglSlot;
23591 function bindTexture( webglType, webglTexture, webglSlot ) {
23595 if ( currentTextureSlot ===
null ) {
23597 webglSlot = gl.TEXTURE0 + maxTextures - 1;
23601 webglSlot = currentTextureSlot;
23607 let boundTexture = currentBoundTextures[ webglSlot ];
23612 currentBoundTextures[ webglSlot ] = boundTexture;
23616 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) {
23618 if ( currentTextureSlot !== webglSlot ) {
23620 gl.activeTexture( webglSlot );
23621 currentTextureSlot = webglSlot;
23625 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] );
23627 boundTexture.type = webglType;
23628 boundTexture.texture = webglTexture;
23634 function unbindTexture() {
23636 const boundTexture = currentBoundTextures[ currentTextureSlot ];
23640 gl.bindTexture( boundTexture.type,
null );
23649 function compressedTexImage2D() {
23653 gl.compressedTexImage2D.apply( gl, arguments );
23655 }
catch ( error ) {
23657 console.error(
'THREE.WebGLState:', error );
23663 function compressedTexImage3D() {
23667 gl.compressedTexImage3D.apply( gl, arguments );
23669 }
catch ( error ) {
23671 console.error(
'THREE.WebGLState:', error );
23677 function texSubImage2D() {
23681 gl.texSubImage2D.apply( gl, arguments );
23683 }
catch ( error ) {
23685 console.error(
'THREE.WebGLState:', error );
23691 function texSubImage3D() {
23695 gl.texSubImage3D.apply( gl, arguments );
23697 }
catch ( error ) {
23699 console.error(
'THREE.WebGLState:', error );
23705 function compressedTexSubImage2D() {
23709 gl.compressedTexSubImage2D.apply( gl, arguments );
23711 }
catch ( error ) {
23713 console.error(
'THREE.WebGLState:', error );
23719 function compressedTexSubImage3D() {
23723 gl.compressedTexSubImage3D.apply( gl, arguments );
23725 }
catch ( error ) {
23727 console.error(
'THREE.WebGLState:', error );
23733 function texStorage2D() {
23737 gl.texStorage2D.apply( gl, arguments );
23739 }
catch ( error ) {
23741 console.error(
'THREE.WebGLState:', error );
23747 function texStorage3D() {
23751 gl.texStorage3D.apply( gl, arguments );
23753 }
catch ( error ) {
23755 console.error(
'THREE.WebGLState:', error );
23761 function texImage2D() {
23765 gl.texImage2D.apply( gl, arguments );
23767 }
catch ( error ) {
23769 console.error(
'THREE.WebGLState:', error );
23775 function texImage3D() {
23779 gl.texImage3D.apply( gl, arguments );
23781 }
catch ( error ) {
23783 console.error(
'THREE.WebGLState:', error );
23791 function scissor( scissor ) {
23793 if ( currentScissor.equals( scissor ) ===
false ) {
23795 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w );
23796 currentScissor.copy( scissor );
23802 function viewport( viewport ) {
23804 if ( currentViewport.equals( viewport ) ===
false ) {
23806 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w );
23807 currentViewport.copy( viewport );
23813 function updateUBOMapping( uniformsGroup, program ) {
23815 let mapping = uboProgramMap.get( program );
23819 mapping =
new WeakMap();
23821 uboProgramMap.set( program, mapping );
23825 let blockIndex = mapping.get( uniformsGroup );
23829 blockIndex = gl.getUniformBlockIndex( program, uniformsGroup.name );
23831 mapping.set( uniformsGroup, blockIndex );
23837 function uniformBlockBinding( uniformsGroup, program ) {
23839 const mapping = uboProgramMap.get( program );
23840 const blockIndex = mapping.get( uniformsGroup );
23842 if ( uboBindings.get( program ) !== blockIndex ) {
23845 gl.uniformBlockBinding( program, blockIndex, uniformsGroup.__bindingPointIndex );
23847 uboBindings.set( program, blockIndex );
23859 gl.disable( gl.BLEND );
23860 gl.disable( gl.CULL_FACE );
23861 gl.disable( gl.DEPTH_TEST );
23862 gl.disable( gl.POLYGON_OFFSET_FILL );
23863 gl.disable( gl.SCISSOR_TEST );
23864 gl.disable( gl.STENCIL_TEST );
23865 gl.disable( gl.SAMPLE_ALPHA_TO_COVERAGE );
23867 gl.blendEquation( gl.FUNC_ADD );
23868 gl.blendFunc( gl.ONE, gl.ZERO );
23869 gl.blendFuncSeparate( gl.ONE, gl.ZERO, gl.ONE, gl.ZERO );
23870 gl.blendColor( 0, 0, 0, 0 );
23872 gl.colorMask(
true,
true,
true,
true );
23873 gl.clearColor( 0, 0, 0, 0 );
23875 gl.depthMask(
true );
23876 gl.depthFunc( gl.LESS );
23877 gl.clearDepth( 1 );
23879 gl.stencilMask( 0xffffffff );
23880 gl.stencilFunc( gl.ALWAYS, 0, 0xffffffff );
23881 gl.stencilOp( gl.KEEP, gl.KEEP, gl.KEEP );
23882 gl.clearStencil( 0 );
23884 gl.cullFace( gl.BACK );
23885 gl.frontFace( gl.CCW );
23887 gl.polygonOffset( 0, 0 );
23889 gl.activeTexture( gl.TEXTURE0 );
23891 gl.bindFramebuffer( gl.FRAMEBUFFER,
null );
23893 if ( isWebGL2 ===
true ) {
23895 gl.bindFramebuffer( gl.DRAW_FRAMEBUFFER,
null );
23896 gl.bindFramebuffer( gl.READ_FRAMEBUFFER,
null );
23900 gl.useProgram(
null );
23904 gl.scissor( 0, 0, gl.canvas.width, gl.canvas.height );
23905 gl.viewport( 0, 0, gl.canvas.width, gl.canvas.height );
23909 enabledCapabilities = {};
23911 currentTextureSlot =
null;
23912 currentBoundTextures = {};
23914 currentBoundFramebuffers = {};
23915 currentDrawbuffers =
new WeakMap();
23916 defaultDrawbuffers = [];
23918 currentProgram =
null;
23920 currentBlendingEnabled =
false;
23921 currentBlending =
null;
23922 currentBlendEquation =
null;
23923 currentBlendSrc =
null;
23924 currentBlendDst =
null;
23925 currentBlendEquationAlpha =
null;
23926 currentBlendSrcAlpha =
null;
23927 currentBlendDstAlpha =
null;
23928 currentBlendColor =
new Color( 0, 0, 0 );
23929 currentBlendAlpha = 0;
23930 currentPremultipledAlpha =
false;
23932 currentFlipSided =
null;
23933 currentCullFace =
null;
23935 currentLineWidth =
null;
23937 currentPolygonOffsetFactor =
null;
23938 currentPolygonOffsetUnits =
null;
23940 currentScissor.set( 0, 0, gl.canvas.width, gl.canvas.height );
23941 currentViewport.set( 0, 0, gl.canvas.width, gl.canvas.height );
23943 colorBuffer.reset();
23944 depthBuffer.reset();
23945 stencilBuffer.reset();
23952 color: colorBuffer,
23953 depth: depthBuffer,
23954 stencil: stencilBuffer
23960 bindFramebuffer: bindFramebuffer,
23961 drawBuffers: drawBuffers,
23963 useProgram: useProgram,
23965 setBlending: setBlending,
23966 setMaterial: setMaterial,
23968 setFlipSided: setFlipSided,
23969 setCullFace: setCullFace,
23971 setLineWidth: setLineWidth,
23972 setPolygonOffset: setPolygonOffset,
23974 setScissorTest: setScissorTest,
23976 activeTexture: activeTexture,
23977 bindTexture: bindTexture,
23978 unbindTexture: unbindTexture,
23979 compressedTexImage2D: compressedTexImage2D,
23980 compressedTexImage3D: compressedTexImage3D,
23981 texImage2D: texImage2D,
23982 texImage3D: texImage3D,
23984 updateUBOMapping: updateUBOMapping,
23985 uniformBlockBinding: uniformBlockBinding,
23987 texStorage2D: texStorage2D,
23988 texStorage3D: texStorage3D,
23989 texSubImage2D: texSubImage2D,
23990 texSubImage3D: texSubImage3D,
23991 compressedTexSubImage2D: compressedTexSubImage2D,
23992 compressedTexSubImage3D: compressedTexSubImage3D,
23995 viewport: viewport,
24003 function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) {
24005 const isWebGL2 = capabilities.isWebGL2;
24006 const multisampledRTTExt = extensions.has(
'WEBGL_multisampled_render_to_texture' ) ? extensions.get(
'WEBGL_multisampled_render_to_texture' ) :
null;
24007 const supportsInvalidateFramebuffer = typeof navigator ===
'undefined' ? false : /OculusBrowser/
g.test( navigator.userAgent );
24009 const _videoTextures =
new WeakMap();
24012 const _sources =
new WeakMap();
24018 let useOffscreenCanvas =
false;
24022 useOffscreenCanvas = typeof OffscreenCanvas !==
'undefined'
24024 && (
new OffscreenCanvas( 1, 1 ).getContext(
'2d' ) ) !==
null;
24032 function createCanvas( width, height ) {
24036 return useOffscreenCanvas ?
24038 new OffscreenCanvas( width, height ) : createElementNS(
'canvas' );
24042 function resizeImage( image, needsPowerOfTwo, needsNewCanvas, maxSize ) {
24048 if ( image.width > maxSize || image.height > maxSize ) {
24050 scale = maxSize /
Math.max( image.width, image.height );
24056 if ( scale < 1 || needsPowerOfTwo ===
true ) {
24060 if ( ( typeof HTMLImageElement !==
'undefined' && image instanceof HTMLImageElement ) ||
24061 ( typeof HTMLCanvasElement !==
'undefined' && image instanceof HTMLCanvasElement ) ||
24062 ( typeof ImageBitmap !==
'undefined' && image instanceof ImageBitmap ) ) {
24064 const floor = needsPowerOfTwo ? floorPowerOfTwo :
Math.floor;
24066 const width =
floor( scale * image.width );
24067 const height =
floor( scale * image.height );
24069 if ( _canvas ===
undefined ) _canvas = createCanvas( width, height );
24073 const canvas = needsNewCanvas ? createCanvas( width, height ) : _canvas;
24075 canvas.width = width;
24076 canvas.height = height;
24078 const context = canvas.getContext(
'2d' );
24079 context.drawImage( image, 0, 0, width, height );
24081 console.warn(
'THREE.WebGLRenderer: Texture has been resized from (' + image.width +
'x' + image.height +
') to (' + width +
'x' + height +
').' );
24087 if (
'data' in image ) {
24089 console.warn(
'THREE.WebGLRenderer: Image in DataTexture is too big (' + image.width +
'x' + image.height +
').' );
24103 function isPowerOfTwo$1( image ) {
24105 return isPowerOfTwo( image.width ) && isPowerOfTwo( image.height );
24109 function textureNeedsPowerOfTwo( texture ) {
24111 if ( isWebGL2 )
return false;
24118 function textureNeedsGenerateMipmaps( texture, supportsMips ) {
24120 return texture.generateMipmaps && supportsMips &&
24125 function generateMipmap( target ) {
24127 _gl.generateMipmap( target );
24131 function getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer =
false ) {
24133 if ( isWebGL2 ===
false )
return glFormat;
24135 if ( internalFormatName !==
null ) {
24137 if ( _gl[ internalFormatName ] !==
undefined )
return _gl[ internalFormatName ];
24139 console.warn(
'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName +
'\'' );
24143 let internalFormat = glFormat;
24145 if ( glFormat === _gl.RED ) {
24147 if ( glType === _gl.FLOAT ) internalFormat = _gl.R32F;
24148 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.R16F;
24149 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8;
24153 if ( glFormat === _gl.RED_INTEGER ) {
24155 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.R8UI;
24156 if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.R16UI;
24157 if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.R32UI;
24158 if ( glType === _gl.BYTE ) internalFormat = _gl.R8I;
24159 if ( glType === _gl.SHORT ) internalFormat = _gl.R16I;
24160 if ( glType === _gl.INT ) internalFormat = _gl.R32I;
24164 if ( glFormat === _gl.RG ) {
24166 if ( glType === _gl.FLOAT ) internalFormat = _gl.RG32F;
24167 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RG16F;
24168 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RG8;
24172 if ( glFormat === _gl.RGBA ) {
24174 const transfer = forceLinearTransfer ? LinearTransfer : ColorManagement.getTransfer( colorSpace );
24176 if ( glType === _gl.FLOAT ) internalFormat = _gl.RGBA32F;
24177 if ( glType === _gl.HALF_FLOAT ) internalFormat = _gl.RGBA16F;
24178 if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = ( transfer === SRGBTransfer ) ? _gl.SRGB8_ALPHA8 : _gl.RGBA8;
24179 if ( glType === _gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = _gl.RGBA4;
24180 if ( glType === _gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = _gl.RGB5_A1;
24184 if ( internalFormat === _gl.R16F || internalFormat === _gl.R32F ||
24185 internalFormat === _gl.RG16F || internalFormat === _gl.RG32F ||
24186 internalFormat === _gl.RGBA16F || internalFormat === _gl.RGBA32F ) {
24188 extensions.get(
'EXT_color_buffer_float' );
24192 return internalFormat;
24196 function getMipLevels( texture, image, supportsMips ) {
24198 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ===
true || ( texture.isFramebufferTexture && texture.minFilter !==
NearestFilter && texture.minFilter !==
LinearFilter ) ) {
24200 return Math.log2(
Math.max( image.width, image.height ) ) + 1;
24202 }
else if ( texture.mipmaps !==
undefined && texture.mipmaps.length > 0 ) {
24206 return texture.mipmaps.length;
24208 }
else if ( texture.isCompressedTexture &&
Array.isArray( texture.image ) ) {
24210 return image.mipmaps.length;
24224 function filterFallback(
f ) {
24226 if (
f ===
NearestFilter ||
f === NearestMipmapNearestFilter ||
f === NearestMipmapLinearFilter ) {
24228 return _gl.NEAREST;
24238 function onTextureDispose( event ) {
24240 const texture =
event.target;
24242 texture.removeEventListener(
'dispose', onTextureDispose );
24244 deallocateTexture( texture );
24246 if ( texture.isVideoTexture ) {
24248 _videoTextures.delete( texture );
24254 function onRenderTargetDispose( event ) {
24256 const renderTarget =
event.target;
24258 renderTarget.removeEventListener(
'dispose', onRenderTargetDispose );
24260 deallocateRenderTarget( renderTarget );
24266 function deallocateTexture( texture ) {
24268 const textureProperties = properties.get( texture );
24270 if ( textureProperties.__webglInit ===
undefined )
return;
24274 const source = texture.source;
24275 const webglTextures = _sources.get( source );
24277 if ( webglTextures ) {
24279 const webglTexture = webglTextures[ textureProperties.__cacheKey ];
24280 webglTexture.usedTimes --;
24284 if ( webglTexture.usedTimes === 0 ) {
24286 deleteTexture( texture );
24292 if ( Object.keys( webglTextures ).length === 0 ) {
24294 _sources.delete( source );
24300 properties.remove( texture );
24304 function deleteTexture( texture ) {
24306 const textureProperties = properties.get( texture );
24307 _gl.deleteTexture( textureProperties.__webglTexture );
24309 const source = texture.source;
24310 const webglTextures = _sources.get( source );
24311 delete webglTextures[ textureProperties.__cacheKey ];
24313 info.memory.textures --;
24317 function deallocateRenderTarget( renderTarget ) {
24319 const texture = renderTarget.texture;
24321 const renderTargetProperties = properties.get( renderTarget );
24322 const textureProperties = properties.get( texture );
24324 if ( textureProperties.__webglTexture !==
undefined ) {
24326 _gl.deleteTexture( textureProperties.__webglTexture );
24328 info.memory.textures --;
24332 if ( renderTarget.depthTexture ) {
24334 renderTarget.depthTexture.dispose();
24338 if ( renderTarget.isWebGLCubeRenderTarget ) {
24340 for ( let
i = 0;
i < 6;
i ++ ) {
24342 if (
Array.isArray( renderTargetProperties.__webglFramebuffer[
i ] ) ) {
24344 for ( let level = 0; level < renderTargetProperties.__webglFramebuffer[
i ].length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[
i ][ level ] );
24348 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[
i ] );
24352 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[
i ] );
24358 if (
Array.isArray( renderTargetProperties.__webglFramebuffer ) ) {
24360 for ( let level = 0; level < renderTargetProperties.__webglFramebuffer.length; level ++ ) _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ level ] );
24364 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer );
24368 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer );
24369 if ( renderTargetProperties.__webglMultisampledFramebuffer ) _gl.deleteFramebuffer( renderTargetProperties.__webglMultisampledFramebuffer );
24371 if ( renderTargetProperties.__webglColorRenderbuffer ) {
24373 for ( let
i = 0;
i < renderTargetProperties.__webglColorRenderbuffer.length;
i ++ ) {
24375 if ( renderTargetProperties.__webglColorRenderbuffer[
i ] ) _gl.deleteRenderbuffer( renderTargetProperties.__webglColorRenderbuffer[
i ] );
24381 if ( renderTargetProperties.__webglDepthRenderbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthRenderbuffer );
24385 if ( renderTarget.isWebGLMultipleRenderTargets ) {
24387 for ( let
i = 0, il = texture.length;
i < il;
i ++ ) {
24389 const attachmentProperties = properties.get( texture[
i ] );
24391 if ( attachmentProperties.__webglTexture ) {
24393 _gl.deleteTexture( attachmentProperties.__webglTexture );
24395 info.memory.textures --;
24399 properties.remove( texture[
i ] );
24405 properties.remove( texture );
24406 properties.remove( renderTarget );
24412 let textureUnits = 0;
24414 function resetTextureUnits() {
24420 function allocateTextureUnit() {
24422 const textureUnit = textureUnits;
24424 if ( textureUnit >= capabilities.maxTextures ) {
24426 console.warn(
'THREE.WebGLTextures: Trying to use ' + textureUnit +
' texture units while this GPU supports only ' + capabilities.maxTextures );
24432 return textureUnit;
24436 function getTextureCacheKey( texture ) {
24440 array.push( texture.wrapS );
24441 array.push( texture.wrapT );
24442 array.push( texture.wrapR || 0 );
24443 array.push( texture.magFilter );
24444 array.push( texture.minFilter );
24445 array.push( texture.anisotropy );
24446 array.push( texture.internalFormat );
24447 array.push( texture.format );
24448 array.push( texture.type );
24449 array.push( texture.generateMipmaps );
24450 array.push( texture.premultiplyAlpha );
24451 array.push( texture.flipY );
24452 array.push( texture.unpackAlignment );
24453 array.push( texture.colorSpace );
24455 return array.join();
24461 function setTexture2D( texture, slot ) {
24463 const textureProperties = properties.get( texture );
24465 if ( texture.isVideoTexture ) updateVideoTexture( texture );
24467 if ( texture.isRenderTargetTexture ===
false && texture.version > 0 && textureProperties.__version !== texture.version ) {
24469 const image = texture.image;
24471 if ( image ===
null ) {
24473 console.warn(
'THREE.WebGLRenderer: Texture marked for update but no image data found.' );
24475 }
else if ( image.complete ===
false ) {
24477 console.warn(
'THREE.WebGLRenderer: Texture marked for update but image is incomplete' );
24481 uploadTexture( textureProperties, texture, slot );
24488 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24492 function setTexture2DArray( texture, slot ) {
24494 const textureProperties = properties.get( texture );
24496 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24498 uploadTexture( textureProperties, texture, slot );
24503 state.bindTexture( _gl.TEXTURE_2D_ARRAY, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24507 function setTexture3D( texture, slot ) {
24509 const textureProperties = properties.get( texture );
24511 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24513 uploadTexture( textureProperties, texture, slot );
24518 state.bindTexture( _gl.TEXTURE_3D, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24522 function setTextureCube( texture, slot ) {
24524 const textureProperties = properties.get( texture );
24526 if ( texture.version > 0 && textureProperties.__version !== texture.version ) {
24528 uploadCubeTexture( textureProperties, texture, slot );
24533 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24537 const wrappingToGL = {
24543 const filterToGL = {
24545 [ NearestMipmapNearestFilter ]: _gl.NEAREST_MIPMAP_NEAREST,
24546 [ NearestMipmapLinearFilter ]: _gl.NEAREST_MIPMAP_LINEAR,
24549 [ LinearMipmapNearestFilter ]: _gl.LINEAR_MIPMAP_NEAREST,
24550 [ LinearMipmapLinearFilter ]: _gl.LINEAR_MIPMAP_LINEAR
24553 const compareToGL = {
24554 [ NeverCompare ]: _gl.NEVER,
24555 [ AlwaysCompare ]: _gl.ALWAYS,
24556 [ LessCompare ]: _gl.LESS,
24557 [ LessEqualCompare ]: _gl.LEQUAL,
24558 [ EqualCompare ]: _gl.EQUAL,
24559 [ GreaterEqualCompare ]: _gl.GEQUAL,
24560 [ GreaterCompare ]: _gl.GREATER,
24561 [ NotEqualCompare ]: _gl.NOTEQUAL
24564 function setTextureParameters( textureType, texture, supportsMips ) {
24566 if ( supportsMips ) {
24568 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] );
24569 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] );
24571 if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) {
24573 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] );
24577 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] );
24578 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterToGL[ texture.minFilter ] );
24582 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
24583 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
24585 if ( textureType === _gl.TEXTURE_3D || textureType === _gl.TEXTURE_2D_ARRAY ) {
24587 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_R, _gl.CLAMP_TO_EDGE );
24593 console.warn(
'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.' );
24597 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
24598 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
24602 console.warn(
'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.' );
24608 if ( texture.compareFunction ) {
24610 _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_MODE, _gl.COMPARE_REF_TO_TEXTURE );
24611 _gl.texParameteri( textureType, _gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] );
24615 if ( extensions.has(
'EXT_texture_filter_anisotropic' ) ===
true ) {
24617 const extension = extensions.get(
'EXT_texture_filter_anisotropic' );
24620 if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter )
return;
24621 if ( texture.type ===
FloatType && extensions.has(
'OES_texture_float_linear' ) ===
false )
return;
24622 if ( isWebGL2 ===
false && ( texture.type === HalfFloatType && extensions.has(
'OES_texture_half_float_linear' ) ===
false ) )
return;
24624 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) {
24626 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT,
Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) );
24627 properties.get( texture ).__currentAnisotropy = texture.anisotropy;
24635 function initTexture( textureProperties, texture ) {
24637 let forceUpload =
false;
24639 if ( textureProperties.__webglInit ===
undefined ) {
24641 textureProperties.__webglInit =
true;
24643 texture.addEventListener(
'dispose', onTextureDispose );
24649 const source = texture.source;
24650 let webglTextures = _sources.get( source );
24654 webglTextures = {};
24655 _sources.set( source, webglTextures );
24661 const textureCacheKey = getTextureCacheKey( texture );
24663 if ( textureCacheKey !== textureProperties.__cacheKey ) {
24667 if ( webglTextures[ textureCacheKey ] ===
undefined ) {
24671 webglTextures[ textureCacheKey ] = {
24672 texture: _gl.createTexture(),
24676 info.memory.textures ++;
24681 forceUpload =
true;
24685 webglTextures[ textureCacheKey ].usedTimes ++;
24690 const webglTexture = webglTextures[ textureProperties.__cacheKey ];
24694 webglTextures[ textureProperties.__cacheKey ].usedTimes --;
24696 if ( webglTexture.usedTimes === 0 ) {
24698 deleteTexture( texture );
24706 textureProperties.__cacheKey = textureCacheKey;
24707 textureProperties.__webglTexture = webglTextures[ textureCacheKey ].texture;
24711 return forceUpload;
24715 function uploadTexture( textureProperties, texture, slot ) {
24717 let textureType = _gl.TEXTURE_2D;
24719 if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) textureType = _gl.TEXTURE_2D_ARRAY;
24720 if ( texture.isData3DTexture ) textureType = _gl.TEXTURE_3D;
24722 const forceUpload = initTexture( textureProperties, texture );
24723 const source = texture.source;
24725 state.bindTexture( textureType, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
24727 const sourceProperties = properties.get( source );
24729 if ( source.version !== sourceProperties.__version || forceUpload ===
true ) {
24731 state.activeTexture( _gl.TEXTURE0 + slot );
24733 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
24734 const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
24735 const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
24737 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
24738 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
24739 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
24740 _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
24742 const needsPowerOfTwo = textureNeedsPowerOfTwo( texture ) && isPowerOfTwo$1( texture.image ) ===
false;
24743 let image = resizeImage( texture.image, needsPowerOfTwo,
false, capabilities.maxTextureSize );
24744 image = verifyColorSpace( texture, image );
24746 const supportsMips = isPowerOfTwo$1( image ) || isWebGL2,
24747 glFormat = utils.convert( texture.format, texture.colorSpace );
24749 let glType = utils.convert( texture.type ),
24750 glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture );
24752 setTextureParameters( textureType, texture, supportsMips );
24755 const mipmaps = texture.mipmaps;
24757 const useTexStorage = ( isWebGL2 && texture.isVideoTexture !==
true && glInternalFormat !== RGB_ETC1_Format );
24758 const allocateMemory = ( sourceProperties.__version ===
undefined ) || ( forceUpload ===
true );
24759 const levels = getMipLevels( texture, image, supportsMips );
24761 if ( texture.isDepthTexture ) {
24765 glInternalFormat = _gl.DEPTH_COMPONENT;
24771 glInternalFormat = _gl.DEPTH_COMPONENT32F;
24775 glInternalFormat = _gl.DEPTH_COMPONENT24;
24777 }
else if ( texture.type === UnsignedInt248Type ) {
24779 glInternalFormat = _gl.DEPTH24_STENCIL8;
24783 glInternalFormat = _gl.DEPTH_COMPONENT16;
24791 console.error(
'WebGLRenderer: Floating point depth texture requires WebGL2.' );
24799 if ( texture.format === DepthFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
24806 console.warn(
'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' );
24809 glType = utils.convert( texture.type );
24815 if ( texture.format === DepthStencilFormat && glInternalFormat === _gl.DEPTH_COMPONENT ) {
24819 glInternalFormat = _gl.DEPTH_STENCIL;
24824 if ( texture.type !== UnsignedInt248Type ) {
24826 console.warn(
'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' );
24828 texture.type = UnsignedInt248Type;
24829 glType = utils.convert( texture.type );
24837 if ( allocateMemory ) {
24839 if ( useTexStorage ) {
24841 state.texStorage2D( _gl.TEXTURE_2D, 1, glInternalFormat, image.width, image.height );
24845 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType,
null );
24851 }
else if ( texture.isDataTexture ) {
24857 if ( mipmaps.length > 0 && supportsMips ) {
24859 if ( useTexStorage && allocateMemory ) {
24861 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
24865 for ( let
i = 0, il = mipmaps.length;
i < il;
i ++ ) {
24867 mipmap = mipmaps[
i ];
24869 if ( useTexStorage ) {
24871 state.texSubImage2D( _gl.TEXTURE_2D,
i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
24875 state.texImage2D( _gl.TEXTURE_2D,
i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
24881 texture.generateMipmaps =
false;
24885 if ( useTexStorage ) {
24887 if ( allocateMemory ) {
24889 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
24893 state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, image.width, image.height, glFormat, glType, image.data );
24897 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, image.width, image.height, 0, glFormat, glType, image.data );
24903 }
else if ( texture.isCompressedTexture ) {
24905 if ( texture.isCompressedArrayTexture ) {
24907 if ( useTexStorage && allocateMemory ) {
24909 state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height, image.depth );
24913 for ( let
i = 0, il = mipmaps.length;
i < il;
i ++ ) {
24915 mipmap = mipmaps[
i ];
24919 if ( glFormat !==
null ) {
24921 if ( useTexStorage ) {
24923 state.compressedTexSubImage3D( _gl.TEXTURE_2D_ARRAY,
i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 );
24927 state.compressedTexImage3D( _gl.TEXTURE_2D_ARRAY,
i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, mipmap.data, 0, 0 );
24933 console.warn(
'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
24939 if ( useTexStorage ) {
24941 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY,
i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data );
24945 state.texImage3D( _gl.TEXTURE_2D_ARRAY,
i, glInternalFormat, mipmap.width, mipmap.height, image.depth, 0, glFormat, glType, mipmap.data );
24955 if ( useTexStorage && allocateMemory ) {
24957 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
24961 for ( let
i = 0, il = mipmaps.length;
i < il;
i ++ ) {
24963 mipmap = mipmaps[
i ];
24967 if ( glFormat !==
null ) {
24969 if ( useTexStorage ) {
24971 state.compressedTexSubImage2D( _gl.TEXTURE_2D,
i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
24975 state.compressedTexImage2D( _gl.TEXTURE_2D,
i, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
24981 console.warn(
'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' );
24987 if ( useTexStorage ) {
24989 state.texSubImage2D( _gl.TEXTURE_2D,
i, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
24993 state.texImage2D( _gl.TEXTURE_2D,
i, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
25003 }
else if ( texture.isDataArrayTexture ) {
25005 if ( useTexStorage ) {
25007 if ( allocateMemory ) {
25009 state.texStorage3D( _gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, image.width, image.height, image.depth );
25013 state.texSubImage3D( _gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
25017 state.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
25021 }
else if ( texture.isData3DTexture ) {
25023 if ( useTexStorage ) {
25025 if ( allocateMemory ) {
25027 state.texStorage3D( _gl.TEXTURE_3D, levels, glInternalFormat, image.width, image.height, image.depth );
25031 state.texSubImage3D( _gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data );
25035 state.texImage3D( _gl.TEXTURE_3D, 0, glInternalFormat, image.width, image.height, image.depth, 0, glFormat, glType, image.data );
25039 }
else if ( texture.isFramebufferTexture ) {
25041 if ( allocateMemory ) {
25043 if ( useTexStorage ) {
25045 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
25049 let width = image.width, height = image.height;
25051 for ( let
i = 0;
i < levels;
i ++ ) {
25053 state.texImage2D( _gl.TEXTURE_2D,
i, glInternalFormat, width, height, 0, glFormat, glType,
null );
25072 if ( mipmaps.length > 0 && supportsMips ) {
25074 if ( useTexStorage && allocateMemory ) {
25076 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, mipmaps[ 0 ].width, mipmaps[ 0 ].height );
25080 for ( let
i = 0, il = mipmaps.length;
i < il;
i ++ ) {
25082 mipmap = mipmaps[
i ];
25084 if ( useTexStorage ) {
25086 state.texSubImage2D( _gl.TEXTURE_2D,
i, 0, 0, glFormat, glType, mipmap );
25090 state.texImage2D( _gl.TEXTURE_2D,
i, glInternalFormat, glFormat, glType, mipmap );
25096 texture.generateMipmaps =
false;
25100 if ( useTexStorage ) {
25102 if ( allocateMemory ) {
25104 state.texStorage2D( _gl.TEXTURE_2D, levels, glInternalFormat, image.width, image.height );
25108 state.texSubImage2D( _gl.TEXTURE_2D, 0, 0, 0, glFormat, glType, image );
25112 state.texImage2D( _gl.TEXTURE_2D, 0, glInternalFormat, glFormat, glType, image );
25120 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25122 generateMipmap( textureType );
25126 sourceProperties.__version = source.version;
25128 if ( texture.onUpdate ) texture.onUpdate( texture );
25132 textureProperties.__version = texture.version;
25136 function uploadCubeTexture( textureProperties, texture, slot ) {
25138 if ( texture.image.length !== 6 )
return;
25140 const forceUpload = initTexture( textureProperties, texture );
25141 const source = texture.source;
25143 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture, _gl.TEXTURE0 + slot );
25145 const sourceProperties = properties.get( source );
25147 if ( source.version !== sourceProperties.__version || forceUpload ===
true ) {
25149 state.activeTexture( _gl.TEXTURE0 + slot );
25151 const workingPrimaries = ColorManagement.getPrimaries( ColorManagement.workingColorSpace );
25152 const texturePrimaries = texture.colorSpace === NoColorSpace ? null : ColorManagement.getPrimaries( texture.colorSpace );
25153 const unpackConversion = texture.colorSpace === NoColorSpace || workingPrimaries === texturePrimaries ? _gl.NONE : _gl.BROWSER_DEFAULT_WEBGL;
25155 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
25156 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
25157 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
25158 _gl.pixelStorei( _gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, unpackConversion );
25160 const isCompressed = ( texture.isCompressedTexture || texture.image[ 0 ].isCompressedTexture );
25161 const isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture );
25163 const cubeImage = [];
25165 for ( let
i = 0;
i < 6;
i ++ ) {
25167 if ( ! isCompressed && ! isDataTexture ) {
25169 cubeImage[
i ] = resizeImage( texture.image[
i ],
false,
true, capabilities.maxCubemapSize );
25173 cubeImage[
i ] = isDataTexture ? texture.image[
i ].image : texture.image[
i ];
25177 cubeImage[
i ] = verifyColorSpace( texture, cubeImage[
i ] );
25181 const image = cubeImage[ 0 ],
25182 supportsMips = isPowerOfTwo$1( image ) || isWebGL2,
25183 glFormat = utils.convert( texture.format, texture.colorSpace ),
25184 glType = utils.convert( texture.type ),
25185 glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
25187 const useTexStorage = ( isWebGL2 && texture.isVideoTexture !== true );
25188 const allocateMemory = ( sourceProperties.__version ===
undefined ) || ( forceUpload ===
true );
25189 let levels = getMipLevels( texture, image, supportsMips );
25191 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips );
25195 if ( isCompressed ) {
25197 if ( useTexStorage && allocateMemory ) {
25199 state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, image.width, image.height );
25203 for ( let
i = 0;
i < 6;
i ++ ) {
25205 mipmaps = cubeImage[
i ].mipmaps;
25207 for ( let
j = 0;
j < mipmaps.length;
j ++ ) {
25209 const mipmap = mipmaps[
j ];
25213 if ( glFormat !==
null ) {
25215 if ( useTexStorage ) {
25217 state.compressedTexSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i,
j, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data );
25221 state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i,
j, glInternalFormat, mipmap.width, mipmap.height, 0, mipmap.data );
25227 console.warn(
'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' );
25233 if ( useTexStorage ) {
25235 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i,
j, 0, 0, mipmap.width, mipmap.height, glFormat, glType, mipmap.data );
25239 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i,
j, glInternalFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
25251 mipmaps = texture.mipmaps;
25253 if ( useTexStorage && allocateMemory ) {
25259 if ( mipmaps.length > 0 ) levels ++;
25261 state.texStorage2D( _gl.TEXTURE_CUBE_MAP, levels, glInternalFormat, cubeImage[ 0 ].width, cubeImage[ 0 ].height );
25265 for ( let
i = 0;
i < 6;
i ++ ) {
25267 if ( isDataTexture ) {
25269 if ( useTexStorage ) {
25271 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i, 0, 0, 0, cubeImage[
i ].width, cubeImage[
i ].height, glFormat, glType, cubeImage[
i ].data );
25275 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i, 0, glInternalFormat, cubeImage[
i ].width, cubeImage[
i ].height, 0, glFormat, glType, cubeImage[
i ].data );
25279 for ( let
j = 0;
j < mipmaps.length;
j ++ ) {
25281 const mipmap = mipmaps[
j ];
25282 const mipmapImage = mipmap.image[
i ].image;
25284 if ( useTexStorage ) {
25286 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i,
j + 1, 0, 0, mipmapImage.width, mipmapImage.height, glFormat, glType, mipmapImage.data );
25290 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i,
j + 1, glInternalFormat, mipmapImage.width, mipmapImage.height, 0, glFormat, glType, mipmapImage.data );
25298 if ( useTexStorage ) {
25300 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i, 0, 0, 0, glFormat, glType, cubeImage[
i ] );
25304 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i, 0, glInternalFormat, glFormat, glType, cubeImage[
i ] );
25308 for ( let
j = 0;
j < mipmaps.length;
j ++ ) {
25310 const mipmap = mipmaps[
j ];
25312 if ( useTexStorage ) {
25314 state.texSubImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i,
j + 1, 0, 0, glFormat, glType, mipmap.image[
i ] );
25318 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i,
j + 1, glInternalFormat, glFormat, glType, mipmap.image[
i ] );
25330 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25333 generateMipmap( _gl.TEXTURE_CUBE_MAP );
25337 sourceProperties.__version = source.version;
25339 if ( texture.onUpdate ) texture.onUpdate( texture );
25343 textureProperties.__version = texture.version;
25350 function setupFrameBufferTexture( framebuffer, renderTarget, texture, attachment, textureTarget, level ) {
25352 const glFormat = utils.convert( texture.format, texture.colorSpace );
25353 const glType = utils.convert( texture.type );
25354 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
25355 const renderTargetProperties = properties.get( renderTarget );
25357 if ( ! renderTargetProperties.__hasExternalTextures ) {
25359 const width =
Math.max( 1, renderTarget.width >> level );
25360 const height =
Math.max( 1, renderTarget.height >> level );
25362 if ( textureTarget === _gl.TEXTURE_3D || textureTarget === _gl.TEXTURE_2D_ARRAY ) {
25364 state.texImage3D( textureTarget, level, glInternalFormat, width, height, renderTarget.depth, 0, glFormat, glType,
null );
25368 state.texImage2D( textureTarget, level, glInternalFormat, width, height, 0, glFormat, glType,
null );
25374 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
25376 if ( useMultisampledRTT( renderTarget ) ) {
25378 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, 0, getRenderTargetSamples( renderTarget ) );
25380 }
else if ( textureTarget === _gl.TEXTURE_2D || ( textureTarget >= _gl.TEXTURE_CUBE_MAP_POSITIVE_X && textureTarget <= _gl.TEXTURE_CUBE_MAP_NEGATIVE_Z ) ) {
25382 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( texture ).__webglTexture, level );
25386 state.bindFramebuffer( _gl.FRAMEBUFFER,
null );
25392 function setupRenderBufferStorage( renderbuffer, renderTarget, isMultisample ) {
25394 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
25396 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
25398 let glInternalFormat = ( isWebGL2 === true ) ? _gl.DEPTH_COMPONENT24 : _gl.DEPTH_COMPONENT16;
25400 if ( isMultisample || useMultisampledRTT( renderTarget ) ) {
25402 const depthTexture = renderTarget.depthTexture;
25404 if ( depthTexture && depthTexture.isDepthTexture ) {
25406 if ( depthTexture.type ===
FloatType ) {
25408 glInternalFormat = _gl.DEPTH_COMPONENT32F;
25412 glInternalFormat = _gl.DEPTH_COMPONENT24;
25418 const samples = getRenderTargetSamples( renderTarget );
25420 if ( useMultisampledRTT( renderTarget ) ) {
25422 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25426 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25432 _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );
25436 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
25438 }
else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
25440 const samples = getRenderTargetSamples( renderTarget );
25442 if ( isMultisample && useMultisampledRTT( renderTarget ) ===
false ) {
25444 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );
25446 }
else if ( useMultisampledRTT( renderTarget ) ) {
25448 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, _gl.DEPTH24_STENCIL8, renderTarget.width, renderTarget.height );
25452 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
25457 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
25461 const textures = renderTarget.isWebGLMultipleRenderTargets ===
true ? renderTarget.texture : [ renderTarget.texture ];
25463 for ( let
i = 0;
i < textures.length;
i ++ ) {
25465 const texture = textures[
i ];
25467 const glFormat = utils.convert( texture.format, texture.colorSpace );
25468 const glType = utils.convert( texture.type );
25469 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace );
25470 const samples = getRenderTargetSamples( renderTarget );
25472 if ( isMultisample && useMultisampledRTT( renderTarget ) ===
false ) {
25474 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25476 }
else if ( useMultisampledRTT( renderTarget ) ) {
25478 multisampledRTTExt.renderbufferStorageMultisampleEXT( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25482 _gl.renderbufferStorage( _gl.RENDERBUFFER, glInternalFormat, renderTarget.width, renderTarget.height );
25490 _gl.bindRenderbuffer( _gl.RENDERBUFFER,
null );
25495 function setupDepthTexture( framebuffer, renderTarget ) {
25497 const isCube = ( renderTarget && renderTarget.isWebGLCubeRenderTarget );
25498 if ( isCube )
throw new Error(
'Depth Texture with cube render targets is not supported' );
25500 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
25502 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) {
25504 throw new Error(
'renderTarget.depthTexture must be an instance of THREE.DepthTexture' );
25509 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture ||
25510 renderTarget.depthTexture.image.width !== renderTarget.width ||
25511 renderTarget.depthTexture.image.height !== renderTarget.height ) {
25513 renderTarget.depthTexture.image.width = renderTarget.width;
25514 renderTarget.depthTexture.image.height = renderTarget.height;
25515 renderTarget.depthTexture.needsUpdate =
true;
25519 setTexture2D( renderTarget.depthTexture, 0 );
25521 const webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture;
25522 const samples = getRenderTargetSamples( renderTarget );
25524 if ( renderTarget.depthTexture.format === DepthFormat ) {
25526 if ( useMultisampledRTT( renderTarget ) ) {
25528 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples );
25532 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
25536 }
else if ( renderTarget.depthTexture.format === DepthStencilFormat ) {
25538 if ( useMultisampledRTT( renderTarget ) ) {
25540 multisampledRTTExt.framebufferTexture2DMultisampleEXT( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0, samples );
25544 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 );
25550 throw new Error(
'Unknown depthTexture format' );
25557 function setupDepthRenderbuffer( renderTarget ) {
25559 const renderTargetProperties = properties.get( renderTarget );
25560 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25562 if ( renderTarget.depthTexture && ! renderTargetProperties.__autoAllocateDepthBuffer ) {
25564 if ( isCube )
throw new Error(
'target.depthTexture not supported in Cube render targets' );
25566 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget );
25572 renderTargetProperties.__webglDepthbuffer = [];
25574 for ( let
i = 0;
i < 6;
i ++ ) {
25576 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[
i ] );
25577 renderTargetProperties.__webglDepthbuffer[
i ] = _gl.createRenderbuffer();
25578 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[
i ], renderTarget,
false );
25584 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25585 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer();
25586 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget,
false );
25592 state.bindFramebuffer( _gl.FRAMEBUFFER,
null );
25597 function rebindTextures( renderTarget, colorTexture, depthTexture ) {
25599 const renderTargetProperties = properties.get( renderTarget );
25603 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, renderTarget.texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, 0 );
25609 setupDepthRenderbuffer( renderTarget );
25616 function setupRenderTarget( renderTarget ) {
25618 const texture = renderTarget.texture;
25620 const renderTargetProperties = properties.get( renderTarget );
25621 const textureProperties = properties.get( texture );
25623 renderTarget.addEventListener(
'dispose', onRenderTargetDispose );
25625 if ( renderTarget.isWebGLMultipleRenderTargets !==
true ) {
25627 if ( textureProperties.__webglTexture ===
undefined ) {
25629 textureProperties.__webglTexture = _gl.createTexture();
25633 textureProperties.__version = texture.version;
25634 info.memory.textures ++;
25638 const isCube = ( renderTarget.isWebGLCubeRenderTarget === true );
25639 const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true );
25640 const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2;
25646 renderTargetProperties.__webglFramebuffer = [];
25648 for ( let
i = 0;
i < 6;
i ++ ) {
25650 if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) {
25652 renderTargetProperties.__webglFramebuffer[
i ] = [];
25654 for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25656 renderTargetProperties.__webglFramebuffer[
i ][ level ] = _gl.createFramebuffer();
25662 renderTargetProperties.__webglFramebuffer[
i ] = _gl.createFramebuffer();
25670 if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) {
25672 renderTargetProperties.__webglFramebuffer = [];
25674 for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25676 renderTargetProperties.__webglFramebuffer[ level ] = _gl.createFramebuffer();
25682 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer();
25686 if ( isMultipleRenderTargets ) {
25688 if ( capabilities.drawBuffers ) {
25690 const textures = renderTarget.texture;
25692 for ( let
i = 0, il = textures.length;
i < il;
i ++ ) {
25694 const attachmentProperties = properties.get( textures[
i ] );
25696 if ( attachmentProperties.__webglTexture ===
undefined ) {
25698 attachmentProperties.__webglTexture = _gl.createTexture();
25700 info.memory.textures ++;
25708 console.warn(
'THREE.WebGLRenderer: WebGLMultipleRenderTargets can only be used with WebGL2 or WEBGL_draw_buffers extension.' );
25714 if ( ( isWebGL2 && renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) ===
false ) {
25716 const textures = isMultipleRenderTargets ? texture : [ texture ];
25718 renderTargetProperties.__webglMultisampledFramebuffer = _gl.createFramebuffer();
25719 renderTargetProperties.__webglColorRenderbuffer = [];
25721 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25723 for ( let
i = 0;
i < textures.length;
i ++ ) {
25725 const texture = textures[
i ];
25726 renderTargetProperties.__webglColorRenderbuffer[
i ] = _gl.createRenderbuffer();
25728 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[
i ] );
25730 const glFormat = utils.convert( texture.format, texture.colorSpace );
25731 const glType = utils.convert( texture.type );
25732 const glInternalFormat = getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, renderTarget.isXRRenderTarget ===
true );
25733 const samples = getRenderTargetSamples( renderTarget );
25734 _gl.renderbufferStorageMultisample( _gl.RENDERBUFFER, samples, glInternalFormat, renderTarget.width, renderTarget.height );
25736 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 +
i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[
i ] );
25740 _gl.bindRenderbuffer( _gl.RENDERBUFFER,
null );
25742 if ( renderTarget.depthBuffer ) {
25744 renderTargetProperties.__webglDepthRenderbuffer = _gl.createRenderbuffer();
25745 setupRenderBufferStorage( renderTargetProperties.__webglDepthRenderbuffer, renderTarget,
true );
25749 state.bindFramebuffer( _gl.FRAMEBUFFER,
null );
25759 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture );
25760 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, supportsMips );
25762 for ( let
i = 0;
i < 6;
i ++ ) {
25764 if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) {
25766 for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25768 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[
i ][ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i, level );
25774 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[
i ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X +
i, 0 );
25780 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25782 generateMipmap( _gl.TEXTURE_CUBE_MAP );
25786 state.unbindTexture();
25788 }
else if ( isMultipleRenderTargets ) {
25790 const textures = renderTarget.texture;
25792 for ( let
i = 0, il = textures.length;
i < il;
i ++ ) {
25794 const attachment = textures[
i ];
25795 const attachmentProperties = properties.get( attachment );
25797 state.bindTexture( _gl.TEXTURE_2D, attachmentProperties.__webglTexture );
25798 setTextureParameters( _gl.TEXTURE_2D, attachment, supportsMips );
25799 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, attachment, _gl.COLOR_ATTACHMENT0 +
i, _gl.TEXTURE_2D, 0 );
25801 if ( textureNeedsGenerateMipmaps( attachment, supportsMips ) ) {
25803 generateMipmap( _gl.TEXTURE_2D );
25809 state.unbindTexture();
25813 let glTextureType = _gl.TEXTURE_2D;
25815 if ( renderTarget.isWebGL3DRenderTarget || renderTarget.isWebGLArrayRenderTarget ) {
25819 glTextureType = renderTarget.isWebGL3DRenderTarget ? _gl.TEXTURE_3D : _gl.TEXTURE_2D_ARRAY;
25823 console.error(
'THREE.WebGLTextures: THREE.Data3DTexture and THREE.DataArrayTexture only supported with WebGL2.' );
25829 state.bindTexture( glTextureType, textureProperties.__webglTexture );
25830 setTextureParameters( glTextureType, texture, supportsMips );
25832 if ( isWebGL2 && texture.mipmaps && texture.mipmaps.length > 0 ) {
25834 for ( let level = 0; level < texture.mipmaps.length; level ++ ) {
25836 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ level ], renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, level );
25842 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, texture, _gl.COLOR_ATTACHMENT0, glTextureType, 0 );
25846 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25848 generateMipmap( glTextureType );
25852 state.unbindTexture();
25858 if ( renderTarget.depthBuffer ) {
25860 setupDepthRenderbuffer( renderTarget );
25866 function updateRenderTargetMipmap( renderTarget ) {
25868 const supportsMips = isPowerOfTwo$1( renderTarget ) || isWebGL2;
25870 const textures = renderTarget.isWebGLMultipleRenderTargets ===
true ? renderTarget.texture : [ renderTarget.texture ];
25872 for ( let
i = 0, il = textures.length;
i < il;
i ++ ) {
25874 const texture = textures[
i ];
25876 if ( textureNeedsGenerateMipmaps( texture, supportsMips ) ) {
25878 const target = renderTarget.isWebGLCubeRenderTarget ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D;
25879 const webglTexture = properties.get( texture ).__webglTexture;
25881 state.bindTexture( target, webglTexture );
25882 generateMipmap( target );
25883 state.unbindTexture();
25891 function updateMultisampleRenderTarget( renderTarget ) {
25893 if ( ( isWebGL2 && renderTarget.samples > 0 ) && useMultisampledRTT( renderTarget ) ===
false ) {
25895 const textures = renderTarget.isWebGLMultipleRenderTargets ? renderTarget.texture : [ renderTarget.texture ];
25896 const width = renderTarget.width;
25897 const height = renderTarget.height;
25898 let mask = _gl.COLOR_BUFFER_BIT;
25899 const invalidationArray = [];
25900 const depthStyle = renderTarget.stencilBuffer ? _gl.DEPTH_STENCIL_ATTACHMENT : _gl.DEPTH_ATTACHMENT;
25901 const renderTargetProperties = properties.get( renderTarget );
25902 const isMultipleRenderTargets = ( renderTarget.isWebGLMultipleRenderTargets === true );
25905 if ( isMultipleRenderTargets ) {
25907 for ( let
i = 0;
i < textures.length;
i ++ ) {
25909 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25910 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 +
i, _gl.RENDERBUFFER,
null );
25912 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25913 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 +
i, _gl.TEXTURE_2D,
null, 0 );
25919 state.bindFramebuffer( _gl.READ_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25920 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25922 for ( let
i = 0;
i < textures.length;
i ++ ) {
25924 invalidationArray.push( _gl.COLOR_ATTACHMENT0 +
i );
25926 if ( renderTarget.depthBuffer ) {
25928 invalidationArray.push( depthStyle );
25932 const ignoreDepthValues = ( renderTargetProperties.__ignoreDepthValues !==
undefined ) ? renderTargetProperties.__ignoreDepthValues : false;
25934 if ( ignoreDepthValues ===
false ) {
25936 if ( renderTarget.depthBuffer ) mask |= _gl.DEPTH_BUFFER_BIT;
25937 if ( renderTarget.stencilBuffer ) mask |= _gl.STENCIL_BUFFER_BIT;
25941 if ( isMultipleRenderTargets ) {
25943 _gl.framebufferRenderbuffer( _gl.READ_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[
i ] );
25947 if ( ignoreDepthValues ===
true ) {
25949 _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, [ depthStyle ] );
25950 _gl.invalidateFramebuffer( _gl.DRAW_FRAMEBUFFER, [ depthStyle ] );
25954 if ( isMultipleRenderTargets ) {
25956 const webglTexture = properties.get( textures[
i ] ).__webglTexture;
25957 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D, webglTexture, 0 );
25961 _gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, _gl.NEAREST );
25963 if ( supportsInvalidateFramebuffer ) {
25965 _gl.invalidateFramebuffer( _gl.READ_FRAMEBUFFER, invalidationArray );
25972 state.bindFramebuffer( _gl.READ_FRAMEBUFFER,
null );
25973 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER,
null );
25976 if ( isMultipleRenderTargets ) {
25978 for ( let
i = 0;
i < textures.length;
i ++ ) {
25980 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25981 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 +
i, _gl.RENDERBUFFER, renderTargetProperties.__webglColorRenderbuffer[
i ] );
25983 const webglTexture = properties.get( textures[
i ] ).__webglTexture;
25985 state.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
25986 _gl.framebufferTexture2D( _gl.DRAW_FRAMEBUFFER, _gl.COLOR_ATTACHMENT0 +
i, _gl.TEXTURE_2D, webglTexture, 0 );
25992 state.bindFramebuffer( _gl.DRAW_FRAMEBUFFER, renderTargetProperties.__webglMultisampledFramebuffer );
25998 function getRenderTargetSamples( renderTarget ) {
26000 return Math.min( capabilities.maxSamples, renderTarget.samples );
26004 function useMultisampledRTT( renderTarget ) {
26006 const renderTargetProperties = properties.get( renderTarget );
26008 return isWebGL2 && renderTarget.samples > 0 && extensions.has(
'WEBGL_multisampled_render_to_texture' ) ===
true && renderTargetProperties.__useRenderToTexture !==
false;
26012 function updateVideoTexture( texture ) {
26014 const frame = info.render.frame;
26018 if ( _videoTextures.get( texture ) !== frame ) {
26020 _videoTextures.set( texture, frame );
26027 function verifyColorSpace( texture, image ) {
26029 const colorSpace = texture.colorSpace;
26030 const format = texture.format;
26031 const type = texture.type;
26033 if ( texture.isCompressedTexture ===
true || texture.isVideoTexture ===
true || texture.format === _SRGBAFormat )
return image;
26035 if ( colorSpace !== LinearSRGBColorSpace && colorSpace !== NoColorSpace ) {
26039 if ( ColorManagement.getTransfer( colorSpace ) === SRGBTransfer ) {
26041 if ( isWebGL2 ===
false ) {
26045 if ( extensions.has(
'EXT_sRGB' ) ===
true && format ===
RGBAFormat ) {
26047 texture.format = _SRGBAFormat;
26052 texture.generateMipmaps =
false;
26068 console.warn(
'THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType.' );
26076 console.error(
'THREE.WebGLTextures: Unsupported texture color space:', colorSpace );
26088 this.allocateTextureUnit = allocateTextureUnit;
26089 this.resetTextureUnits = resetTextureUnits;
26091 this.setTexture2D = setTexture2D;
26092 this.setTexture2DArray = setTexture2DArray;
26093 this.setTexture3D = setTexture3D;
26094 this.setTextureCube = setTextureCube;
26095 this.rebindTextures = rebindTextures;
26096 this.setupRenderTarget = setupRenderTarget;
26097 this.updateRenderTargetMipmap = updateRenderTargetMipmap;
26098 this.updateMultisampleRenderTarget = updateMultisampleRenderTarget;
26099 this.setupDepthRenderbuffer = setupDepthRenderbuffer;
26100 this.setupFrameBufferTexture = setupFrameBufferTexture;
26101 this.useMultisampledRTT = useMultisampledRTT;
26105 function WebGLUtils( gl, extensions, capabilities ) {
26107 const isWebGL2 = capabilities.isWebGL2;
26109 function convert(
p, colorSpace = NoColorSpace ) {
26113 const transfer = ColorManagement.getTransfer( colorSpace );
26122 if (
p ===
IntType )
return gl.INT;
26126 if (
p === HalfFloatType ) {
26128 if ( isWebGL2 )
return gl.HALF_FLOAT;
26130 extension = extensions.get(
'OES_texture_half_float' );
26132 if ( extension !==
null ) {
26134 return extension.HALF_FLOAT_OES;
26148 if (
p === DepthFormat )
return gl.DEPTH_COMPONENT;
26149 if (
p === DepthStencilFormat )
return gl.DEPTH_STENCIL;
26153 if (
p === _SRGBAFormat ) {
26155 extension = extensions.get(
'EXT_sRGB' );
26157 if ( extension !==
null ) {
26159 return extension.SRGB_ALPHA_EXT;
26171 if (
p === RedFormat )
return gl.RED;
26172 if (
p === RedIntegerFormat )
return gl.RED_INTEGER;
26173 if (
p === RGFormat )
return gl.RG;
26174 if (
p === RGIntegerFormat )
return gl.RG_INTEGER;
26175 if (
p === RGBAIntegerFormat )
return gl.RGBA_INTEGER;
26181 if ( transfer === SRGBTransfer ) {
26183 extension = extensions.get(
'WEBGL_compressed_texture_s3tc_srgb' );
26185 if ( extension !==
null ) {
26200 extension = extensions.get(
'WEBGL_compressed_texture_s3tc' );
26202 if ( extension !==
null ) {
26221 if (
p === RGB_PVRTC_4BPPV1_Format ||
p === RGB_PVRTC_2BPPV1_Format ||
p === RGBA_PVRTC_4BPPV1_Format ||
p === RGBA_PVRTC_2BPPV1_Format ) {
26223 extension = extensions.get(
'WEBGL_compressed_texture_pvrtc' );
26225 if ( extension !==
null ) {
26227 if (
p === RGB_PVRTC_4BPPV1_Format )
return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
26228 if (
p === RGB_PVRTC_2BPPV1_Format )
return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
26229 if (
p === RGBA_PVRTC_4BPPV1_Format )
return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
26230 if (
p === RGBA_PVRTC_2BPPV1_Format )
return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
26242 if (
p === RGB_ETC1_Format ) {
26244 extension = extensions.get(
'WEBGL_compressed_texture_etc1' );
26246 if ( extension !==
null ) {
26248 return extension.COMPRESSED_RGB_ETC1_WEBGL;
26260 if (
p === RGB_ETC2_Format ||
p === RGBA_ETC2_EAC_Format ) {
26262 extension = extensions.get(
'WEBGL_compressed_texture_etc' );
26264 if ( extension !==
null ) {
26266 if (
p === RGB_ETC2_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2;
26267 if (
p === RGBA_ETC2_EAC_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC;
26279 if (
p === RGBA_ASTC_4x4_Format ||
p === RGBA_ASTC_5x4_Format ||
p === RGBA_ASTC_5x5_Format ||
26280 p === RGBA_ASTC_6x5_Format ||
p === RGBA_ASTC_6x6_Format ||
p === RGBA_ASTC_8x5_Format ||
26281 p === RGBA_ASTC_8x6_Format ||
p === RGBA_ASTC_8x8_Format ||
p === RGBA_ASTC_10x5_Format ||
26282 p === RGBA_ASTC_10x6_Format ||
p === RGBA_ASTC_10x8_Format ||
p === RGBA_ASTC_10x10_Format ||
26283 p === RGBA_ASTC_12x10_Format ||
p === RGBA_ASTC_12x12_Format ) {
26285 extension = extensions.get(
'WEBGL_compressed_texture_astc' );
26287 if ( extension !==
null ) {
26289 if (
p === RGBA_ASTC_4x4_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR;
26290 if (
p === RGBA_ASTC_5x4_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR;
26291 if (
p === RGBA_ASTC_5x5_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR;
26292 if (
p === RGBA_ASTC_6x5_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR;
26293 if (
p === RGBA_ASTC_6x6_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR;
26294 if (
p === RGBA_ASTC_8x5_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR;
26295 if (
p === RGBA_ASTC_8x6_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR;
26296 if (
p === RGBA_ASTC_8x8_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR;
26297 if (
p === RGBA_ASTC_10x5_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR;
26298 if (
p === RGBA_ASTC_10x6_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR;
26299 if (
p === RGBA_ASTC_10x8_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR;
26300 if (
p === RGBA_ASTC_10x10_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR;
26301 if (
p === RGBA_ASTC_12x10_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR;
26302 if (
p === RGBA_ASTC_12x12_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR;
26314 if (
p === RGBA_BPTC_Format ||
p === RGB_BPTC_SIGNED_Format ||
p === RGB_BPTC_UNSIGNED_Format ) {
26316 extension = extensions.get(
'EXT_texture_compression_bptc' );
26318 if ( extension !==
null ) {
26320 if (
p === RGBA_BPTC_Format )
return ( transfer === SRGBTransfer ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT;
26321 if (
p === RGB_BPTC_SIGNED_Format )
return extension.COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT;
26322 if (
p === RGB_BPTC_UNSIGNED_Format )
return extension.COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT;
26334 if (
p === RED_RGTC1_Format ||
p === SIGNED_RED_RGTC1_Format ||
p === RED_GREEN_RGTC2_Format ||
p === SIGNED_RED_GREEN_RGTC2_Format ) {
26336 extension = extensions.get(
'EXT_texture_compression_rgtc' );
26338 if ( extension !==
null ) {
26340 if (
p === RGBA_BPTC_Format )
return extension.COMPRESSED_RED_RGTC1_EXT;
26341 if (
p === SIGNED_RED_RGTC1_Format )
return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT;
26342 if (
p === RED_GREEN_RGTC2_Format )
return extension.COMPRESSED_RED_GREEN_RGTC2_EXT;
26343 if (
p === SIGNED_RED_GREEN_RGTC2_Format )
return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT;
26355 if (
p === UnsignedInt248Type ) {
26357 if ( isWebGL2 )
return gl.UNSIGNED_INT_24_8;
26359 extension = extensions.get(
'WEBGL_depth_texture' );
26361 if ( extension !==
null ) {
26363 return extension.UNSIGNED_INT_24_8_WEBGL;
26375 return ( gl[
p ] !==
undefined ) ? gl[
p ] :
null;
26379 return { convert: convert };
26385 constructor( array = [] ) {
26389 this.isArrayCamera =
true;
26391 this.cameras = array;
26403 this.isGroup =
true;
26405 this.type =
'Group';
26411 const _moveEvent = { type:
'move' };
26413 class WebXRController {
26417 this._targetRay =
null;
26425 if ( this._hand ===
null ) {
26427 this._hand =
new Group();
26428 this._hand.matrixAutoUpdate =
false;
26429 this._hand.visible =
false;
26431 this._hand.joints = {};
26432 this._hand.inputState = { pinching:
false };
26440 getTargetRaySpace() {
26442 if ( this._targetRay ===
null ) {
26444 this._targetRay =
new Group();
26445 this._targetRay.matrixAutoUpdate =
false;
26446 this._targetRay.visible =
false;
26447 this._targetRay.hasLinearVelocity =
false;
26448 this._targetRay.linearVelocity =
new Vector3();
26449 this._targetRay.hasAngularVelocity =
false;
26450 this._targetRay.angularVelocity =
new Vector3();
26454 return this._targetRay;
26460 if ( this._grip ===
null ) {
26462 this._grip =
new Group();
26463 this._grip.matrixAutoUpdate =
false;
26464 this._grip.visible =
false;
26465 this._grip.hasLinearVelocity =
false;
26466 this._grip.linearVelocity =
new Vector3();
26467 this._grip.hasAngularVelocity =
false;
26468 this._grip.angularVelocity =
new Vector3();
26476 dispatchEvent( event ) {
26478 if ( this._targetRay !==
null ) {
26480 this._targetRay.dispatchEvent( event );
26484 if ( this._grip !==
null ) {
26486 this._grip.dispatchEvent( event );
26490 if ( this._hand !==
null ) {
26492 this._hand.dispatchEvent( event );
26500 connect( inputSource ) {
26502 if ( inputSource && inputSource.hand ) {
26504 const hand = this._hand;
26508 for (
const inputjoint of inputSource.hand.values() ) {
26511 this._getHandJoint( hand, inputjoint );
26519 this.dispatchEvent( { type:
'connected', data: inputSource } );
26525 disconnect( inputSource ) {
26527 this.dispatchEvent( { type:
'disconnected', data: inputSource } );
26529 if ( this._targetRay !==
null ) {
26531 this._targetRay.visible =
false;
26535 if ( this._grip !==
null ) {
26537 this._grip.visible =
false;
26541 if ( this._hand !==
null ) {
26543 this._hand.visible =
false;
26551 update( inputSource, frame, referenceSpace ) {
26553 let inputPose =
null;
26554 let gripPose =
null;
26555 let handPose =
null;
26557 const targetRay = this._targetRay;
26558 const grip = this._grip;
26559 const hand = this._hand;
26561 if ( inputSource && frame.session.visibilityState !==
'visible-blurred' ) {
26563 if ( hand && inputSource.hand ) {
26567 for (
const inputjoint of inputSource.hand.values() ) {
26570 const jointPose = frame.getJointPose( inputjoint, referenceSpace );
26573 const joint = this._getHandJoint( hand, inputjoint );
26575 if ( jointPose !==
null ) {
26577 joint.matrix.fromArray( jointPose.transform.matrix );
26578 joint.matrix.decompose( joint.position, joint.rotation, joint.scale );
26579 joint.matrixWorldNeedsUpdate =
true;
26580 joint.jointRadius = jointPose.radius;
26584 joint.visible = jointPose !==
null;
26591 const indexTip = hand.joints[
'index-finger-tip' ];
26592 const thumbTip = hand.joints[
'thumb-tip' ];
26593 const distance = indexTip.position.distanceTo( thumbTip.position );
26595 const distanceToPinch = 0.02;
26596 const threshold = 0.005;
26598 if ( hand.inputState.pinching && distance > distanceToPinch + threshold ) {
26600 hand.inputState.pinching =
false;
26601 this.dispatchEvent( {
26603 handedness: inputSource.handedness,
26607 }
else if ( ! hand.inputState.pinching && distance <= distanceToPinch - threshold ) {
26609 hand.inputState.pinching =
true;
26610 this.dispatchEvent( {
26611 type:
'pinchstart',
26612 handedness: inputSource.handedness,
26620 if ( grip !==
null && inputSource.gripSpace ) {
26622 gripPose = frame.getPose( inputSource.gripSpace, referenceSpace );
26624 if ( gripPose !==
null ) {
26626 grip.matrix.fromArray( gripPose.transform.matrix );
26627 grip.matrix.decompose( grip.position, grip.rotation, grip.scale );
26628 grip.matrixWorldNeedsUpdate =
true;
26630 if ( gripPose.linearVelocity ) {
26632 grip.hasLinearVelocity =
true;
26633 grip.linearVelocity.copy( gripPose.linearVelocity );
26637 grip.hasLinearVelocity =
false;
26641 if ( gripPose.angularVelocity ) {
26643 grip.hasAngularVelocity =
true;
26644 grip.angularVelocity.copy( gripPose.angularVelocity );
26648 grip.hasAngularVelocity =
false;
26658 if ( targetRay !==
null ) {
26660 inputPose = frame.getPose( inputSource.targetRaySpace, referenceSpace );
26663 if ( inputPose ===
null && gripPose !==
null ) {
26665 inputPose = gripPose;
26669 if ( inputPose !==
null ) {
26671 targetRay.matrix.fromArray( inputPose.transform.matrix );
26672 targetRay.matrix.decompose( targetRay.position, targetRay.rotation, targetRay.scale );
26673 targetRay.matrixWorldNeedsUpdate =
true;
26675 if ( inputPose.linearVelocity ) {
26677 targetRay.hasLinearVelocity =
true;
26678 targetRay.linearVelocity.copy( inputPose.linearVelocity );
26682 targetRay.hasLinearVelocity =
false;
26686 if ( inputPose.angularVelocity ) {
26688 targetRay.hasAngularVelocity =
true;
26689 targetRay.angularVelocity.copy( inputPose.angularVelocity );
26693 targetRay.hasAngularVelocity =
false;
26697 this.dispatchEvent( _moveEvent );
26706 if ( targetRay !==
null ) {
26708 targetRay.visible = ( inputPose !== null );
26712 if ( grip !==
null ) {
26714 grip.visible = ( gripPose !== null );
26718 if ( hand !==
null ) {
26720 hand.visible = ( handPose !== null );
26730 _getHandJoint( hand, inputjoint ) {
26732 if ( hand.joints[ inputjoint.jointName ] ===
undefined ) {
26734 const joint =
new Group();
26735 joint.matrixAutoUpdate =
false;
26736 joint.visible =
false;
26737 hand.joints[ inputjoint.jointName ] = joint;
26743 return hand.joints[ inputjoint.jointName ];
26751 constructor( renderer, gl ) {
26755 const scope =
this;
26757 let session =
null;
26759 let framebufferScaleFactor = 1.0;
26761 let referenceSpace =
null;
26762 let referenceSpaceType =
'local-floor';
26764 let foveation = 1.0;
26765 let customReferenceSpace =
null;
26768 let glBinding =
null;
26769 let glProjLayer =
null;
26770 let glBaseLayer =
null;
26771 let xrFrame =
null;
26772 const attributes = gl.getContextAttributes();
26773 let initialRenderTarget =
null;
26774 let newRenderTarget =
null;
26776 const controllers = [];
26777 const controllerInputSources = [];
26779 const currentSize =
new Vector2();
26780 let currentPixelRatio =
null;
26785 cameraL.layers.enable( 1 );
26786 cameraL.viewport =
new Vector4();
26789 cameraR.layers.enable( 2 );
26790 cameraR.viewport =
new Vector4();
26792 const cameras = [ cameraL, cameraR ];
26794 const cameraXR =
new ArrayCamera();
26795 cameraXR.layers.enable( 1 );
26796 cameraXR.layers.enable( 2 );
26798 let _currentDepthNear =
null;
26799 let _currentDepthFar =
null;
26803 this.cameraAutoUpdate =
true;
26804 this.enabled =
false;
26806 this.isPresenting =
false;
26808 this.getController =
function ( index ) {
26810 let controller = controllers[ index ];
26814 controller =
new WebXRController();
26815 controllers[ index ] = controller;
26819 return controller.getTargetRaySpace();
26823 this.getControllerGrip =
function ( index ) {
26825 let controller = controllers[ index ];
26829 controller =
new WebXRController();
26830 controllers[ index ] = controller;
26834 return controller.getGripSpace();
26838 this.getHand =
function ( index ) {
26840 let controller = controllers[ index ];
26844 controller =
new WebXRController();
26845 controllers[ index ] = controller;
26849 return controller.getHandSpace();
26855 function onSessionEvent( event ) {
26857 const controllerIndex = controllerInputSources.indexOf( event.inputSource );
26859 if ( controllerIndex === - 1 ) {
26865 const controller = controllers[ controllerIndex ];
26869 controller.update( event.inputSource, event.frame, customReferenceSpace || referenceSpace );
26870 controller.dispatchEvent( { type:
event.type, data:
event.inputSource } );
26876 function onSessionEnd() {
26878 session.removeEventListener(
'select', onSessionEvent );
26879 session.removeEventListener(
'selectstart', onSessionEvent );
26880 session.removeEventListener(
'selectend', onSessionEvent );
26881 session.removeEventListener(
'squeeze', onSessionEvent );
26882 session.removeEventListener(
'squeezestart', onSessionEvent );
26883 session.removeEventListener(
'squeezeend', onSessionEvent );
26884 session.removeEventListener(
'end', onSessionEnd );
26885 session.removeEventListener(
'inputsourceschange', onInputSourcesChange );
26887 for ( let
i = 0;
i < controllers.length;
i ++ ) {
26889 const inputSource = controllerInputSources[
i ];
26891 if ( inputSource ===
null )
continue;
26893 controllerInputSources[
i ] =
null;
26895 controllers[
i ].disconnect( inputSource );
26899 _currentDepthNear =
null;
26900 _currentDepthFar =
null;
26904 renderer.setRenderTarget( initialRenderTarget );
26906 glBaseLayer =
null;
26907 glProjLayer =
null;
26910 newRenderTarget =
null;
26916 scope.isPresenting =
false;
26918 renderer.setPixelRatio( currentPixelRatio );
26919 renderer.setSize( currentSize.width, currentSize.height,
false );
26921 scope.dispatchEvent( { type:
'sessionend' } );
26925 this.setFramebufferScaleFactor =
function ( value ) {
26927 framebufferScaleFactor = value;
26929 if ( scope.isPresenting ===
true ) {
26931 console.warn(
'THREE.WebXRManager: Cannot change framebuffer scale while presenting.' );
26937 this.setReferenceSpaceType =
function ( value ) {
26939 referenceSpaceType = value;
26941 if ( scope.isPresenting ===
true ) {
26943 console.warn(
'THREE.WebXRManager: Cannot change reference space type while presenting.' );
26949 this.getReferenceSpace =
function () {
26951 return customReferenceSpace || referenceSpace;
26955 this.setReferenceSpace =
function ( space ) {
26957 customReferenceSpace = space;
26961 this.getBaseLayer =
function () {
26963 return glProjLayer !==
null ? glProjLayer : glBaseLayer;
26967 this.getBinding =
function () {
26973 this.getFrame =
function () {
26979 this.getSession =
function () {
26985 this.setSession = async
function ( value ) {
26989 if ( session !==
null ) {
26991 initialRenderTarget = renderer.getRenderTarget();
26993 session.addEventListener(
'select', onSessionEvent );
26994 session.addEventListener(
'selectstart', onSessionEvent );
26995 session.addEventListener(
'selectend', onSessionEvent );
26996 session.addEventListener(
'squeeze', onSessionEvent );
26997 session.addEventListener(
'squeezestart', onSessionEvent );
26998 session.addEventListener(
'squeezeend', onSessionEvent );
26999 session.addEventListener(
'end', onSessionEnd );
27000 session.addEventListener(
'inputsourceschange', onInputSourcesChange );
27002 if ( attributes.xrCompatible !==
true ) {
27004 await gl.makeXRCompatible();
27008 currentPixelRatio = renderer.getPixelRatio();
27009 renderer.getSize( currentSize );
27011 if ( ( session.renderState.layers ===
undefined ) || ( renderer.capabilities.isWebGL2 ===
false ) ) {
27013 const layerInit = {
27014 antialias: ( session.renderState.layers ===
undefined ) ? attributes.antialias : true,
27016 depth: attributes.depth,
27017 stencil: attributes.stencil,
27018 framebufferScaleFactor: framebufferScaleFactor
27021 glBaseLayer =
new XRWebGLLayer( session, gl, layerInit );
27023 session.updateRenderState( { baseLayer: glBaseLayer } );
27025 renderer.setPixelRatio( 1 );
27026 renderer.setSize( glBaseLayer.framebufferWidth, glBaseLayer.framebufferHeight,
false );
27029 glBaseLayer.framebufferWidth,
27030 glBaseLayer.framebufferHeight,
27032 format: RGBAFormat,
27033 type: UnsignedByteType,
27034 colorSpace: renderer.outputColorSpace,
27035 stencilBuffer: attributes.stencil
27041 let depthFormat =
null;
27042 let depthType =
null;
27043 let glDepthFormat =
null;
27045 if ( attributes.depth ) {
27047 glDepthFormat = attributes.stencil ? gl.DEPTH24_STENCIL8 : gl.DEPTH_COMPONENT24;
27048 depthFormat = attributes.stencil ? DepthStencilFormat : DepthFormat;
27049 depthType = attributes.stencil ? UnsignedInt248Type :
UnsignedIntType;
27053 const projectionlayerInit = {
27054 colorFormat: gl.RGBA8,
27055 depthFormat: glDepthFormat,
27056 scaleFactor: framebufferScaleFactor
27059 glBinding =
new XRWebGLBinding( session, gl );
27061 glProjLayer = glBinding.createProjectionLayer( projectionlayerInit );
27063 session.updateRenderState( { layers: [ glProjLayer ] } );
27065 renderer.setPixelRatio( 1 );
27066 renderer.setSize( glProjLayer.textureWidth, glProjLayer.textureHeight,
false );
27069 glProjLayer.textureWidth,
27070 glProjLayer.textureHeight,
27072 format: RGBAFormat,
27073 type: UnsignedByteType,
27074 depthTexture: new DepthTexture( glProjLayer.textureWidth, glProjLayer.textureHeight, depthType, undefined, undefined, undefined, undefined, undefined, undefined, depthFormat ),
27075 stencilBuffer: attributes.stencil,
27076 colorSpace: renderer.outputColorSpace,
27077 samples: attributes.antialias ? 4 : 0
27080 const renderTargetProperties = renderer.properties.get( newRenderTarget );
27081 renderTargetProperties.__ignoreDepthValues = glProjLayer.ignoreDepthValues;
27085 newRenderTarget.isXRRenderTarget =
true;
27087 this.setFoveation( foveation );
27089 customReferenceSpace =
null;
27090 referenceSpace = await session.requestReferenceSpace( referenceSpaceType );
27092 animation.setContext( session );
27095 scope.isPresenting =
true;
27097 scope.dispatchEvent( { type:
'sessionstart' } );
27103 this.getEnvironmentBlendMode =
function () {
27105 if ( session !==
null ) {
27107 return session.environmentBlendMode;
27113 function onInputSourcesChange( event ) {
27117 for ( let
i = 0;
i <
event.removed.length;
i ++ ) {
27119 const inputSource =
event.removed[
i ];
27120 const index = controllerInputSources.indexOf( inputSource );
27122 if ( index >= 0 ) {
27124 controllerInputSources[ index ] =
null;
27125 controllers[ index ].disconnect( inputSource );
27133 for ( let
i = 0;
i <
event.added.length;
i ++ ) {
27135 const inputSource =
event.added[
i ];
27137 let controllerIndex = controllerInputSources.indexOf( inputSource );
27139 if ( controllerIndex === - 1 ) {
27143 for ( let
i = 0;
i < controllers.length;
i ++ ) {
27145 if (
i >= controllerInputSources.length ) {
27147 controllerInputSources.push( inputSource );
27148 controllerIndex =
i;
27151 }
else if ( controllerInputSources[
i ] ===
null ) {
27153 controllerInputSources[
i ] = inputSource;
27154 controllerIndex =
i;
27163 if ( controllerIndex === - 1 )
break;
27167 const controller = controllers[ controllerIndex ];
27169 if ( controller ) {
27171 controller.connect( inputSource );
27181 const cameraLPos =
new Vector3();
27182 const cameraRPos =
new Vector3();
27190 function setProjectionFromUnion( camera, cameraL, cameraR ) {
27192 cameraLPos.setFromMatrixPosition( cameraL.matrixWorld );
27193 cameraRPos.setFromMatrixPosition( cameraR.matrixWorld );
27195 const ipd = cameraLPos.distanceTo( cameraRPos );
27197 const projL = cameraL.projectionMatrix.elements;
27198 const projR = cameraR.projectionMatrix.elements;
27203 const near = projL[ 14 ] / ( projL[ 10 ] - 1 );
27204 const far = projL[ 14 ] / ( projL[ 10 ] + 1 );
27205 const topFov = ( projL[ 9 ] + 1 ) / projL[ 5 ];
27206 const bottomFov = ( projL[ 9 ] - 1 ) / projL[ 5 ];
27208 const leftFov = ( projL[ 8 ] - 1 ) / projL[ 0 ];
27209 const rightFov = ( projR[ 8 ] + 1 ) / projR[ 0 ];
27210 const left = near * leftFov;
27211 const right = near * rightFov;
27215 const zOffset = ipd / ( - leftFov + rightFov );
27216 const xOffset = zOffset * - leftFov;
27219 cameraL.matrixWorld.decompose( camera.position, camera.quaternion, camera.scale );
27220 camera.translateX( xOffset );
27221 camera.translateZ( zOffset );
27222 camera.matrixWorld.compose( camera.position, camera.quaternion, camera.scale );
27223 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
27228 const near2 = near + zOffset;
27229 const far2 = far + zOffset;
27230 const left2 = left - xOffset;
27231 const right2 = right + ( ipd - xOffset );
27232 const top2 = topFov * far / far2 * near2;
27233 const bottom2 = bottomFov * far / far2 * near2;
27235 camera.projectionMatrix.makePerspective( left2, right2, top2, bottom2, near2, far2 );
27236 camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
27240 function updateCamera( camera, parent ) {
27242 if ( parent ===
null ) {
27244 camera.matrixWorld.copy( camera.matrix );
27248 camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix );
27252 camera.matrixWorldInverse.copy( camera.matrixWorld ).invert();
27256 this.updateCamera =
function ( camera ) {
27258 if ( session ===
null )
return;
27260 cameraXR.near = cameraR.near = cameraL.near = camera.near;
27261 cameraXR.far = cameraR.far = cameraL.far = camera.far;
27263 if ( _currentDepthNear !== cameraXR.near || _currentDepthFar !== cameraXR.far ) {
27267 session.updateRenderState( {
27268 depthNear: cameraXR.near,
27269 depthFar: cameraXR.far
27272 _currentDepthNear = cameraXR.near;
27273 _currentDepthFar = cameraXR.far;
27277 const parent = camera.parent;
27278 const cameras = cameraXR.cameras;
27280 updateCamera( cameraXR, parent );
27282 for ( let
i = 0;
i < cameras.length;
i ++ ) {
27284 updateCamera( cameras[
i ], parent );
27290 if ( cameras.length === 2 ) {
27292 setProjectionFromUnion( cameraXR, cameraL, cameraR );
27298 cameraXR.projectionMatrix.copy( cameraL.projectionMatrix );
27304 updateUserCamera( camera, cameraXR, parent );
27308 function updateUserCamera( camera, cameraXR, parent ) {
27310 if ( parent ===
null ) {
27312 camera.matrix.copy( cameraXR.matrixWorld );
27316 camera.matrix.copy( parent.matrixWorld );
27317 camera.matrix.invert();
27318 camera.matrix.multiply( cameraXR.matrixWorld );
27322 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
27323 camera.updateMatrixWorld(
true );
27325 camera.projectionMatrix.copy( cameraXR.projectionMatrix );
27326 camera.projectionMatrixInverse.copy( cameraXR.projectionMatrixInverse );
27328 if ( camera.isPerspectiveCamera ) {
27330 camera.fov = RAD2DEG * 2 *
Math.atan( 1 / camera.projectionMatrix.elements[ 5 ] );
27337 this.getCamera =
function () {
27343 this.getFoveation =
function () {
27345 if ( glProjLayer ===
null && glBaseLayer ===
null ) {
27355 this.setFoveation =
function ( value ) {
27362 if ( glProjLayer !==
null ) {
27364 glProjLayer.fixedFoveation = value;
27368 if ( glBaseLayer !==
null && glBaseLayer.fixedFoveation !==
undefined ) {
27370 glBaseLayer.fixedFoveation = value;
27378 let onAnimationFrameCallback =
null;
27380 function onAnimationFrame( time, frame ) {
27382 pose = frame.getViewerPose( customReferenceSpace || referenceSpace );
27385 if (
pose !==
null ) {
27387 const views =
pose.views;
27389 if ( glBaseLayer !==
null ) {
27391 renderer.setRenderTargetFramebuffer( newRenderTarget, glBaseLayer.framebuffer );
27392 renderer.setRenderTarget( newRenderTarget );
27396 let cameraXRNeedsUpdate =
false;
27400 if ( views.length !== cameraXR.cameras.length ) {
27402 cameraXR.cameras.length = 0;
27403 cameraXRNeedsUpdate =
true;
27407 for ( let
i = 0;
i < views.length;
i ++ ) {
27409 const view = views[
i ];
27411 let viewport =
null;
27413 if ( glBaseLayer !==
null ) {
27415 viewport = glBaseLayer.getViewport( view );
27419 const glSubImage = glBinding.getViewSubImage( glProjLayer, view );
27420 viewport = glSubImage.viewport;
27425 renderer.setRenderTargetTextures(
27427 glSubImage.colorTexture,
27428 glProjLayer.ignoreDepthValues ?
undefined : glSubImage.depthStencilTexture );
27430 renderer.setRenderTarget( newRenderTarget );
27436 let camera = cameras[
i ];
27441 camera.layers.enable(
i );
27442 camera.viewport =
new Vector4();
27443 cameras[
i ] = camera;
27447 camera.matrix.fromArray( view.transform.matrix );
27448 camera.matrix.decompose( camera.position, camera.quaternion, camera.scale );
27449 camera.projectionMatrix.fromArray( view.projectionMatrix );
27450 camera.projectionMatrixInverse.copy( camera.projectionMatrix ).invert();
27451 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height );
27455 cameraXR.matrix.copy( camera.matrix );
27456 cameraXR.matrix.decompose( cameraXR.position, cameraXR.quaternion, cameraXR.scale );
27460 if ( cameraXRNeedsUpdate ===
true ) {
27462 cameraXR.cameras.push( camera );
27472 for ( let
i = 0;
i < controllers.length;
i ++ ) {
27474 const inputSource = controllerInputSources[
i ];
27475 const controller = controllers[
i ];
27477 if ( inputSource !==
null && controller !==
undefined ) {
27479 controller.update( inputSource, frame, customReferenceSpace || referenceSpace );
27485 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time, frame );
27487 if ( frame.detectedPlanes ) {
27489 scope.dispatchEvent( { type:
'planesdetected', data: frame } );
27497 const animation =
new WebGLAnimation();
27499 animation.setAnimationLoop( onAnimationFrame );
27501 this.setAnimationLoop =
function ( callback ) {
27503 onAnimationFrameCallback = callback;
27507 this.
dispose =
function () {};
27513 function WebGLMaterials( renderer, properties ) {
27515 function refreshTransformUniform( map, uniform ) {
27517 if ( map.matrixAutoUpdate ===
true ) {
27519 map.updateMatrix();
27523 uniform.value.copy( map.matrix );
27527 function refreshFogUniforms( uniforms, fog ) {
27529 fog.color.getRGB( uniforms.fogColor.value, getUnlitUniformColorSpace( renderer ) );
27533 uniforms.fogNear.value = fog.near;
27534 uniforms.fogFar.value = fog.far;
27536 }
else if ( fog.isFogExp2 ) {
27538 uniforms.fogDensity.value = fog.density;
27544 function refreshMaterialUniforms( uniforms, material, pixelRatio, height, transmissionRenderTarget ) {
27546 if ( material.isMeshBasicMaterial ) {
27548 refreshUniformsCommon( uniforms, material );
27550 }
else if ( material.isMeshLambertMaterial ) {
27552 refreshUniformsCommon( uniforms, material );
27554 }
else if ( material.isMeshToonMaterial ) {
27556 refreshUniformsCommon( uniforms, material );
27557 refreshUniformsToon( uniforms, material );
27559 }
else if ( material.isMeshPhongMaterial ) {
27561 refreshUniformsCommon( uniforms, material );
27562 refreshUniformsPhong( uniforms, material );
27564 }
else if ( material.isMeshStandardMaterial ) {
27566 refreshUniformsCommon( uniforms, material );
27567 refreshUniformsStandard( uniforms, material );
27569 if ( material.isMeshPhysicalMaterial ) {
27571 refreshUniformsPhysical( uniforms, material, transmissionRenderTarget );
27575 }
else if ( material.isMeshMatcapMaterial ) {
27577 refreshUniformsCommon( uniforms, material );
27578 refreshUniformsMatcap( uniforms, material );
27580 }
else if ( material.isMeshDepthMaterial ) {
27582 refreshUniformsCommon( uniforms, material );
27584 }
else if ( material.isMeshDistanceMaterial ) {
27586 refreshUniformsCommon( uniforms, material );
27587 refreshUniformsDistance( uniforms, material );
27589 }
else if ( material.isMeshNormalMaterial ) {
27591 refreshUniformsCommon( uniforms, material );
27593 }
else if ( material.isLineBasicMaterial ) {
27595 refreshUniformsLine( uniforms, material );
27597 if ( material.isLineDashedMaterial ) {
27599 refreshUniformsDash( uniforms, material );
27603 }
else if ( material.isPointsMaterial ) {
27605 refreshUniformsPoints( uniforms, material, pixelRatio, height );
27607 }
else if ( material.isSpriteMaterial ) {
27609 refreshUniformsSprites( uniforms, material );
27611 }
else if ( material.isShadowMaterial ) {
27613 uniforms.color.value.copy( material.color );
27614 uniforms.opacity.value = material.opacity;
27616 }
else if ( material.isShaderMaterial ) {
27618 material.uniformsNeedUpdate =
false;
27624 function refreshUniformsCommon( uniforms, material ) {
27626 uniforms.opacity.value = material.opacity;
27628 if ( material.color ) {
27630 uniforms.diffuse.value.copy( material.color );
27634 if ( material.emissive ) {
27636 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
27640 if ( material.map ) {
27642 uniforms.map.value = material.map;
27644 refreshTransformUniform( material.map, uniforms.mapTransform );
27648 if ( material.alphaMap ) {
27650 uniforms.alphaMap.value = material.alphaMap;
27652 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27656 if ( material.bumpMap ) {
27658 uniforms.bumpMap.value = material.bumpMap;
27660 refreshTransformUniform( material.bumpMap, uniforms.bumpMapTransform );
27662 uniforms.bumpScale.value = material.bumpScale;
27664 if ( material.side ===
BackSide ) {
27666 uniforms.bumpScale.value *= - 1;
27672 if ( material.normalMap ) {
27674 uniforms.normalMap.value = material.normalMap;
27676 refreshTransformUniform( material.normalMap, uniforms.normalMapTransform );
27678 uniforms.normalScale.value.copy( material.normalScale );
27680 if ( material.side ===
BackSide ) {
27682 uniforms.normalScale.value.negate();
27688 if ( material.displacementMap ) {
27690 uniforms.displacementMap.value = material.displacementMap;
27692 refreshTransformUniform( material.displacementMap, uniforms.displacementMapTransform );
27694 uniforms.displacementScale.value = material.displacementScale;
27695 uniforms.displacementBias.value = material.displacementBias;
27699 if ( material.emissiveMap ) {
27701 uniforms.emissiveMap.value = material.emissiveMap;
27703 refreshTransformUniform( material.emissiveMap, uniforms.emissiveMapTransform );
27707 if ( material.specularMap ) {
27709 uniforms.specularMap.value = material.specularMap;
27711 refreshTransformUniform( material.specularMap, uniforms.specularMapTransform );
27715 if ( material.alphaTest > 0 ) {
27717 uniforms.alphaTest.value = material.alphaTest;
27721 const envMap = properties.get( material ).envMap;
27725 uniforms.envMap.value = envMap;
27727 uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
27729 uniforms.reflectivity.value = material.reflectivity;
27730 uniforms.ior.value = material.ior;
27731 uniforms.refractionRatio.value = material.refractionRatio;
27735 if ( material.lightMap ) {
27737 uniforms.lightMap.value = material.lightMap;
27740 const scaleFactor = ( renderer._useLegacyLights === true ) ?
Math.PI : 1;
27742 uniforms.lightMapIntensity.value = material.lightMapIntensity * scaleFactor;
27744 refreshTransformUniform( material.lightMap, uniforms.lightMapTransform );
27748 if ( material.aoMap ) {
27750 uniforms.aoMap.value = material.aoMap;
27751 uniforms.aoMapIntensity.value = material.aoMapIntensity;
27753 refreshTransformUniform( material.aoMap, uniforms.aoMapTransform );
27759 function refreshUniformsLine( uniforms, material ) {
27761 uniforms.diffuse.value.copy( material.color );
27762 uniforms.opacity.value = material.opacity;
27764 if ( material.map ) {
27766 uniforms.map.value = material.map;
27768 refreshTransformUniform( material.map, uniforms.mapTransform );
27774 function refreshUniformsDash( uniforms, material ) {
27776 uniforms.dashSize.value = material.dashSize;
27777 uniforms.totalSize.value = material.dashSize + material.gapSize;
27778 uniforms.scale.value = material.scale;
27782 function refreshUniformsPoints( uniforms, material, pixelRatio, height ) {
27784 uniforms.diffuse.value.copy( material.color );
27785 uniforms.opacity.value = material.opacity;
27786 uniforms.size.value = material.size * pixelRatio;
27787 uniforms.scale.value = height * 0.5;
27789 if ( material.map ) {
27791 uniforms.map.value = material.map;
27793 refreshTransformUniform( material.map, uniforms.uvTransform );
27797 if ( material.alphaMap ) {
27799 uniforms.alphaMap.value = material.alphaMap;
27801 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27805 if ( material.alphaTest > 0 ) {
27807 uniforms.alphaTest.value = material.alphaTest;
27813 function refreshUniformsSprites( uniforms, material ) {
27815 uniforms.diffuse.value.copy( material.color );
27816 uniforms.opacity.value = material.opacity;
27817 uniforms.rotation.value = material.rotation;
27819 if ( material.map ) {
27821 uniforms.map.value = material.map;
27823 refreshTransformUniform( material.map, uniforms.mapTransform );
27827 if ( material.alphaMap ) {
27829 uniforms.alphaMap.value = material.alphaMap;
27831 refreshTransformUniform( material.alphaMap, uniforms.alphaMapTransform );
27835 if ( material.alphaTest > 0 ) {
27837 uniforms.alphaTest.value = material.alphaTest;
27843 function refreshUniformsPhong( uniforms, material ) {
27845 uniforms.specular.value.copy( material.specular );
27846 uniforms.shininess.value =
Math.max( material.shininess, 1
e-4 );
27850 function refreshUniformsToon( uniforms, material ) {
27852 if ( material.gradientMap ) {
27854 uniforms.gradientMap.value = material.gradientMap;
27860 function refreshUniformsStandard( uniforms, material ) {
27862 uniforms.metalness.value = material.metalness;
27864 if ( material.metalnessMap ) {
27866 uniforms.metalnessMap.value = material.metalnessMap;
27868 refreshTransformUniform( material.metalnessMap, uniforms.metalnessMapTransform );
27872 uniforms.roughness.value = material.roughness;
27874 if ( material.roughnessMap ) {
27876 uniforms.roughnessMap.value = material.roughnessMap;
27878 refreshTransformUniform( material.roughnessMap, uniforms.roughnessMapTransform );
27882 const envMap = properties.get( material ).envMap;
27887 uniforms.envMapIntensity.value = material.envMapIntensity;
27893 function refreshUniformsPhysical( uniforms, material, transmissionRenderTarget ) {
27895 uniforms.ior.value = material.ior;
27897 if ( material.sheen > 0 ) {
27899 uniforms.sheenColor.value.copy( material.sheenColor ).multiplyScalar( material.sheen );
27901 uniforms.sheenRoughness.value = material.sheenRoughness;
27903 if ( material.sheenColorMap ) {
27905 uniforms.sheenColorMap.value = material.sheenColorMap;
27907 refreshTransformUniform( material.sheenColorMap, uniforms.sheenColorMapTransform );
27911 if ( material.sheenRoughnessMap ) {
27913 uniforms.sheenRoughnessMap.value = material.sheenRoughnessMap;
27915 refreshTransformUniform( material.sheenRoughnessMap, uniforms.sheenRoughnessMapTransform );
27921 if ( material.clearcoat > 0 ) {
27923 uniforms.clearcoat.value = material.clearcoat;
27924 uniforms.clearcoatRoughness.value = material.clearcoatRoughness;
27926 if ( material.clearcoatMap ) {
27928 uniforms.clearcoatMap.value = material.clearcoatMap;
27930 refreshTransformUniform( material.clearcoatMap, uniforms.clearcoatMapTransform );
27934 if ( material.clearcoatRoughnessMap ) {
27936 uniforms.clearcoatRoughnessMap.value = material.clearcoatRoughnessMap;
27938 refreshTransformUniform( material.clearcoatRoughnessMap, uniforms.clearcoatRoughnessMapTransform );
27942 if ( material.clearcoatNormalMap ) {
27944 uniforms.clearcoatNormalMap.value = material.clearcoatNormalMap;
27946 refreshTransformUniform( material.clearcoatNormalMap, uniforms.clearcoatNormalMapTransform );
27948 uniforms.clearcoatNormalScale.value.copy( material.clearcoatNormalScale );
27950 if ( material.side ===
BackSide ) {
27952 uniforms.clearcoatNormalScale.value.negate();
27960 if ( material.iridescence > 0 ) {
27962 uniforms.iridescence.value = material.iridescence;
27963 uniforms.iridescenceIOR.value = material.iridescenceIOR;
27964 uniforms.iridescenceThicknessMinimum.value = material.iridescenceThicknessRange[ 0 ];
27965 uniforms.iridescenceThicknessMaximum.value = material.iridescenceThicknessRange[ 1 ];
27967 if ( material.iridescenceMap ) {
27969 uniforms.iridescenceMap.value = material.iridescenceMap;
27971 refreshTransformUniform( material.iridescenceMap, uniforms.iridescenceMapTransform );
27975 if ( material.iridescenceThicknessMap ) {
27977 uniforms.iridescenceThicknessMap.value = material.iridescenceThicknessMap;
27979 refreshTransformUniform( material.iridescenceThicknessMap, uniforms.iridescenceThicknessMapTransform );
27985 if ( material.transmission > 0 ) {
27987 uniforms.transmission.value = material.transmission;
27988 uniforms.transmissionSamplerMap.value = transmissionRenderTarget.texture;
27989 uniforms.transmissionSamplerSize.value.set( transmissionRenderTarget.width, transmissionRenderTarget.height );
27991 if ( material.transmissionMap ) {
27993 uniforms.transmissionMap.value = material.transmissionMap;
27995 refreshTransformUniform( material.transmissionMap, uniforms.transmissionMapTransform );
27999 uniforms.thickness.value = material.thickness;
28001 if ( material.thicknessMap ) {
28003 uniforms.thicknessMap.value = material.thicknessMap;
28005 refreshTransformUniform( material.thicknessMap, uniforms.thicknessMapTransform );
28009 uniforms.attenuationDistance.value = material.attenuationDistance;
28010 uniforms.attenuationColor.value.copy( material.attenuationColor );
28014 if ( material.anisotropy > 0 ) {
28016 uniforms.anisotropyVector.value.set( material.anisotropy *
Math.cos( material.anisotropyRotation ), material.anisotropy *
Math.sin( material.anisotropyRotation ) );
28018 if ( material.anisotropyMap ) {
28020 uniforms.anisotropyMap.value = material.anisotropyMap;
28022 refreshTransformUniform( material.anisotropyMap, uniforms.anisotropyMapTransform );
28028 uniforms.specularIntensity.value = material.specularIntensity;
28029 uniforms.specularColor.value.copy( material.specularColor );
28031 if ( material.specularColorMap ) {
28033 uniforms.specularColorMap.value = material.specularColorMap;
28035 refreshTransformUniform( material.specularColorMap, uniforms.specularColorMapTransform );
28039 if ( material.specularIntensityMap ) {
28041 uniforms.specularIntensityMap.value = material.specularIntensityMap;
28043 refreshTransformUniform( material.specularIntensityMap, uniforms.specularIntensityMapTransform );
28049 function refreshUniformsMatcap( uniforms, material ) {
28051 if ( material.matcap ) {
28053 uniforms.matcap.value = material.matcap;
28059 function refreshUniformsDistance( uniforms, material ) {
28061 const light = properties.get( material ).light;
28063 uniforms.referencePosition.value.setFromMatrixPosition( light.matrixWorld );
28064 uniforms.nearDistance.value = light.shadow.camera.near;
28065 uniforms.farDistance.value = light.shadow.camera.far;
28070 refreshFogUniforms: refreshFogUniforms,
28071 refreshMaterialUniforms: refreshMaterialUniforms
28076 function WebGLUniformsGroups( gl, info, capabilities, state ) {
28079 let updateList = {};
28080 let allocatedBindingPoints = [];
28082 const maxBindingPoints = ( capabilities.isWebGL2 ) ? gl.getParameter( gl.MAX_UNIFORM_BUFFER_BINDINGS ) : 0;
28084 function bind( uniformsGroup, program ) {
28086 const webglProgram = program.program;
28087 state.uniformBlockBinding( uniformsGroup, webglProgram );
28091 function update( uniformsGroup, program ) {
28093 let buffer = buffers[ uniformsGroup.id ];
28097 prepareUniformsGroup( uniformsGroup );
28099 buffer = createBuffer( uniformsGroup );
28100 buffers[ uniformsGroup.id ] = buffer;
28102 uniformsGroup.addEventListener(
'dispose', onUniformsGroupsDispose );
28108 const webglProgram = program.program;
28109 state.updateUBOMapping( uniformsGroup, webglProgram );
28113 const frame = info.render.frame;
28115 if ( updateList[ uniformsGroup.id ] !== frame ) {
28117 updateBufferData( uniformsGroup );
28119 updateList[ uniformsGroup.id ] = frame;
28125 function createBuffer( uniformsGroup ) {
28129 const bindingPointIndex = allocateBindingPointIndex();
28130 uniformsGroup.__bindingPointIndex = bindingPointIndex;
28132 const buffer = gl.createBuffer();
28133 const size = uniformsGroup.__size;
28134 const usage = uniformsGroup.usage;
28136 gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
28137 gl.bufferData( gl.UNIFORM_BUFFER, size, usage );
28138 gl.bindBuffer( gl.UNIFORM_BUFFER,
null );
28139 gl.bindBufferBase( gl.UNIFORM_BUFFER, bindingPointIndex, buffer );
28145 function allocateBindingPointIndex() {
28147 for ( let
i = 0;
i < maxBindingPoints;
i ++ ) {
28149 if ( allocatedBindingPoints.indexOf(
i ) === - 1 ) {
28151 allocatedBindingPoints.push(
i );
28158 console.error(
'THREE.WebGLRenderer: Maximum number of simultaneously usable uniforms groups reached.' );
28164 function updateBufferData( uniformsGroup ) {
28166 const buffer = buffers[ uniformsGroup.id ];
28167 const uniforms = uniformsGroup.uniforms;
28168 const cache = uniformsGroup.__cache;
28170 gl.bindBuffer( gl.UNIFORM_BUFFER, buffer );
28172 for ( let
i = 0, il = uniforms.length;
i < il;
i ++ ) {
28174 const uniformArray =
Array.isArray( uniforms[
i ] ) ? uniforms[
i ] : [ uniforms[
i ] ];
28176 for ( let
j = 0, jl = uniformArray.length;
j < jl;
j ++ ) {
28178 const uniform = uniformArray[
j ];
28180 if ( hasUniformChanged( uniform,
i,
j,
cache ) ===
true ) {
28182 const offset = uniform.__offset;
28184 const values =
Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
28186 let arrayOffset = 0;
28188 for ( let
k = 0;
k < values.length;
k ++ ) {
28190 const value = values[
k ];
28192 const info = getUniformSize( value );
28195 if ( typeof value ===
'number' || typeof value ===
'boolean' ) {
28197 uniform.__data[ 0 ] = value;
28198 gl.bufferSubData( gl.UNIFORM_BUFFER, offset + arrayOffset, uniform.__data );
28200 }
else if ( value.isMatrix3 ) {
28204 uniform.__data[ 0 ] = value.elements[ 0 ];
28205 uniform.__data[ 1 ] = value.elements[ 1 ];
28206 uniform.__data[ 2 ] = value.elements[ 2 ];
28207 uniform.__data[ 3 ] = 0;
28208 uniform.__data[ 4 ] = value.elements[ 3 ];
28209 uniform.__data[ 5 ] = value.elements[ 4 ];
28210 uniform.__data[ 6 ] = value.elements[ 5 ];
28211 uniform.__data[ 7 ] = 0;
28212 uniform.__data[ 8 ] = value.elements[ 6 ];
28213 uniform.__data[ 9 ] = value.elements[ 7 ];
28214 uniform.__data[ 10 ] = value.elements[ 8 ];
28215 uniform.__data[ 11 ] = 0;
28219 value.toArray( uniform.__data, arrayOffset );
28221 arrayOffset += info.storage /
Float32Array.BYTES_PER_ELEMENT;
28227 gl.bufferSubData( gl.UNIFORM_BUFFER, offset, uniform.__data );
28235 gl.bindBuffer( gl.UNIFORM_BUFFER,
null );
28239 function hasUniformChanged( uniform, index, indexArray,
cache ) {
28241 const value = uniform.value;
28242 const indexString = index +
'_' + indexArray;
28248 if ( typeof value ===
'number' || typeof value ===
'boolean' ) {
28250 cache[ indexString ] = value;
28254 cache[ indexString ] = value.clone();
28262 const cachedObject =
cache[ indexString ];
28266 if ( typeof value ===
'number' || typeof value ===
'boolean' ) {
28268 if ( cachedObject !== value ) {
28270 cache[ indexString ] = value;
28277 if ( cachedObject.equals( value ) ===
false ) {
28279 cachedObject.copy( value );
28292 function prepareUniformsGroup( uniformsGroup ) {
28297 const uniforms = uniformsGroup.uniforms;
28300 const chunkSize = 16;
28302 for ( let
i = 0,
l = uniforms.length;
i <
l;
i ++ ) {
28304 const uniformArray =
Array.isArray( uniforms[
i ] ) ? uniforms[
i ] : [ uniforms[
i ] ];
28306 for ( let
j = 0, jl = uniformArray.length;
j < jl;
j ++ ) {
28308 const uniform = uniformArray[
j ];
28310 const values =
Array.isArray( uniform.value ) ? uniform.value : [ uniform.value ];
28312 for ( let
k = 0, kl = values.length;
k < kl;
k ++ ) {
28314 const value = values[
k ];
28316 const info = getUniformSize( value );
28319 const chunkOffsetUniform = offset % chunkSize;
28322 if ( chunkOffsetUniform !== 0 && ( chunkSize - chunkOffsetUniform ) < info.boundary ) {
28325 offset += ( chunkSize - chunkOffsetUniform );
28332 uniform.__offset = offset;
28336 offset += info.storage;
28347 const chunkOffset = offset % chunkSize;
28349 if ( chunkOffset > 0 ) offset += ( chunkSize - chunkOffset );
28353 uniformsGroup.__size = offset;
28354 uniformsGroup.__cache = {};
28360 function getUniformSize( value ) {
28369 if ( typeof value ===
'number' || typeof value ===
'boolean' ) {
28376 }
else if ( value.isVector2 ) {
28383 }
else if ( value.isVector3 || value.isColor ) {
28387 info.boundary = 16;
28390 }
else if ( value.isVector4 ) {
28394 info.boundary = 16;
28397 }
else if ( value.isMatrix3 ) {
28401 info.boundary = 48;
28404 }
else if ( value.isMatrix4 ) {
28408 info.boundary = 64;
28411 }
else if ( value.isTexture ) {
28413 console.warn(
'THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group.' );
28417 console.warn(
'THREE.WebGLRenderer: Unsupported uniform value type.', value );
28425 function onUniformsGroupsDispose( event ) {
28427 const uniformsGroup =
event.target;
28429 uniformsGroup.removeEventListener(
'dispose', onUniformsGroupsDispose );
28431 const index = allocatedBindingPoints.indexOf( uniformsGroup.__bindingPointIndex );
28432 allocatedBindingPoints.splice( index, 1 );
28434 gl.deleteBuffer( buffers[ uniformsGroup.id ] );
28436 delete buffers[ uniformsGroup.id ];
28437 delete updateList[ uniformsGroup.id ];
28443 for (
const id in buffers ) {
28445 gl.deleteBuffer( buffers[
id ] );
28449 allocatedBindingPoints = [];
28468 constructor( parameters = {} ) {
28471 canvas = createCanvasElement(),
28477 premultipliedAlpha =
true,
28478 preserveDrawingBuffer =
false,
28479 powerPreference =
'default',
28480 failIfMajorPerformanceCaveat =
false,
28483 this.isWebGLRenderer =
true;
28487 if ( context !==
null ) {
28489 _alpha = context.getContextAttributes().alpha;
28500 let currentRenderList =
null;
28501 let currentRenderState =
null;
28506 const renderListStack = [];
28507 const renderStateStack = [];
28511 this.domElement = canvas;
28520 checkShaderErrors:
true,
28525 onShaderError:
null
28530 this.autoClear =
true;
28531 this.autoClearColor =
true;
28532 this.autoClearDepth =
true;
28533 this.autoClearStencil =
true;
28537 this.sortObjects =
true;
28541 this.clippingPlanes = [];
28542 this.localClippingEnabled =
false;
28546 this._outputColorSpace = SRGBColorSpace;
28550 this._useLegacyLights =
false;
28554 this.toneMapping = NoToneMapping;
28555 this.toneMappingExposure = 1.0;
28559 const _this =
this;
28561 let _isContextLost =
false;
28565 let _currentActiveCubeFace = 0;
28566 let _currentActiveMipmapLevel = 0;
28567 let _currentRenderTarget =
null;
28568 let _currentMaterialId = - 1;
28570 let _currentCamera =
null;
28572 const _currentViewport =
new Vector4();
28573 const _currentScissor =
new Vector4();
28574 let _currentScissorTest =
null;
28576 const _currentClearColor =
new Color( 0x000000 );
28577 let _currentClearAlpha = 0;
28581 let _width = canvas.width;
28582 let _height = canvas.height;
28584 let _pixelRatio = 1;
28585 let _opaqueSort =
null;
28586 let _transparentSort =
null;
28588 const _viewport =
new Vector4( 0, 0, _width, _height );
28589 const _scissor =
new Vector4( 0, 0, _width, _height );
28590 let _scissorTest =
false;
28594 const _frustum =
new Frustum();
28598 let _clippingEnabled =
false;
28599 let _localClippingEnabled =
false;
28603 let _transmissionRenderTarget =
null;
28607 const _projScreenMatrix =
new Matrix4();
28609 const _vector2 =
new Vector2();
28610 const _vector3 =
new Vector3();
28612 const _emptyScene = { background:
null, fog:
null, environment:
null, overrideMaterial:
null, isScene:
true };
28614 function getTargetPixelRatio() {
28616 return _currentRenderTarget ===
null ? _pixelRatio : 1;
28624 function getContext( contextNames, contextAttributes ) {
28626 for ( let
i = 0;
i < contextNames.length;
i ++ ) {
28628 const contextName = contextNames[
i ];
28629 const context = canvas.getContext( contextName, contextAttributes );
28630 if ( context !==
null )
return context;
28640 const contextAttributes = {
28645 premultipliedAlpha,
28646 preserveDrawingBuffer,
28648 failIfMajorPerformanceCaveat,
28652 if (
'setAttribute' in canvas ) canvas.setAttribute(
'data-engine', `three.js r${REVISION}` );
28655 canvas.addEventListener(
'webglcontextlost', onContextLost,
false );
28656 canvas.addEventListener(
'webglcontextrestored', onContextRestore,
false );
28657 canvas.addEventListener(
'webglcontextcreationerror', onContextCreationError,
false );
28659 if ( _gl ===
null ) {
28661 const contextNames = [
'webgl2',
'webgl',
'experimental-webgl' ];
28663 if ( _this.isWebGL1Renderer ===
true ) {
28665 contextNames.shift();
28669 _gl = getContext( contextNames, contextAttributes );
28671 if ( _gl ===
null ) {
28673 if ( getContext( contextNames ) ) {
28675 throw new Error(
'Error creating WebGL context with your selected attributes.' );
28679 throw new Error(
'Error creating WebGL context.' );
28687 if ( typeof WebGLRenderingContext !==
'undefined' && _gl instanceof WebGLRenderingContext ) {
28689 console.warn(
'THREE.WebGLRenderer: WebGL 1 support was deprecated in r153 and will be removed in r163.' );
28695 if ( _gl.getShaderPrecisionFormat ===
undefined ) {
28697 _gl.getShaderPrecisionFormat =
function () {
28699 return {
'rangeMin': 1,
'rangeMax': 1,
'precision': 1 };
28705 }
catch ( error ) {
28707 console.error(
'THREE.WebGLRenderer: ' + error.message );
28712 let extensions, capabilities, state, info;
28713 let properties, textures, cubemaps, cubeuvmaps, attributes, geometries, objects;
28714 let programCache, materials, renderLists, renderStates, clipping, shadowMap;
28716 let background, morphtargets, bufferRenderer, indexedBufferRenderer;
28718 let utils, bindingStates, uniformsGroups;
28720 function initGLContext() {
28722 extensions =
new WebGLExtensions( _gl );
28724 capabilities =
new WebGLCapabilities( _gl, extensions, parameters );
28726 extensions.init( capabilities );
28728 utils =
new WebGLUtils( _gl, extensions, capabilities );
28730 state =
new WebGLState( _gl, extensions, capabilities );
28732 info =
new WebGLInfo( _gl );
28733 properties =
new WebGLProperties();
28734 textures =
new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
28735 cubemaps =
new WebGLCubeMaps( _this );
28736 cubeuvmaps =
new WebGLCubeUVMaps( _this );
28737 attributes =
new WebGLAttributes( _gl, capabilities );
28738 bindingStates =
new WebGLBindingStates( _gl, extensions, attributes, capabilities );
28739 geometries =
new WebGLGeometries( _gl, attributes, info, bindingStates );
28740 objects =
new WebGLObjects( _gl, geometries, attributes, info );
28741 morphtargets =
new WebGLMorphtargets( _gl, capabilities, textures );
28742 clipping =
new WebGLClipping( properties );
28743 programCache =
new WebGLPrograms( _this, cubemaps, cubeuvmaps, extensions, capabilities, bindingStates, clipping );
28744 materials =
new WebGLMaterials( _this, properties );
28745 renderLists =
new WebGLRenderLists();
28746 renderStates =
new WebGLRenderStates( extensions, capabilities );
28747 background =
new WebGLBackground( _this, cubemaps, cubeuvmaps, state, objects, _alpha, premultipliedAlpha );
28748 shadowMap =
new WebGLShadowMap( _this, objects, capabilities );
28749 uniformsGroups =
new WebGLUniformsGroups( _gl, info, capabilities, state );
28751 bufferRenderer =
new WebGLBufferRenderer( _gl, extensions, info, capabilities );
28752 indexedBufferRenderer =
new WebGLIndexedBufferRenderer( _gl, extensions, info, capabilities );
28754 info.programs = programCache.programs;
28756 _this.capabilities = capabilities;
28757 _this.extensions = extensions;
28758 _this.properties = properties;
28759 _this.renderLists = renderLists;
28760 _this.shadowMap = shadowMap;
28761 _this.state = state;
28770 const xr =
new WebXRManager( _this, _gl );
28776 this.getContext =
function () {
28782 this.getContextAttributes =
function () {
28784 return _gl.getContextAttributes();
28788 this.forceContextLoss =
function () {
28790 const extension = extensions.get(
'WEBGL_lose_context' );
28791 if ( extension ) extension.loseContext();
28795 this.forceContextRestore =
function () {
28797 const extension = extensions.get(
'WEBGL_lose_context' );
28798 if ( extension ) extension.restoreContext();
28802 this.getPixelRatio =
function () {
28804 return _pixelRatio;
28808 this.setPixelRatio =
function ( value ) {
28812 _pixelRatio = value;
28814 this.setSize( _width, _height,
false );
28818 this.getSize =
function ( target ) {
28820 return target.set( _width, _height );
28824 this.setSize =
function ( width, height, updateStyle = true ) {
28826 if ( xr.isPresenting ) {
28828 console.warn(
'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' );
28836 canvas.width =
Math.floor( width * _pixelRatio );
28837 canvas.height =
Math.floor( height * _pixelRatio );
28839 if ( updateStyle ===
true ) {
28841 canvas.style.width = width +
'px';
28842 canvas.style.height = height +
'px';
28846 this.setViewport( 0, 0, width, height );
28850 this.getDrawingBufferSize =
function ( target ) {
28852 return target.set( _width * _pixelRatio, _height * _pixelRatio ).floor();
28856 this.setDrawingBufferSize =
function ( width, height, pixelRatio ) {
28861 _pixelRatio = pixelRatio;
28863 canvas.width =
Math.floor( width * pixelRatio );
28864 canvas.height =
Math.floor( height * pixelRatio );
28866 this.setViewport( 0, 0, width, height );
28870 this.getCurrentViewport =
function ( target ) {
28872 return target.copy( _currentViewport );
28876 this.getViewport =
function ( target ) {
28878 return target.copy( _viewport );
28882 this.setViewport =
function (
x,
y, width, height ) {
28884 if (
x.isVector4 ) {
28886 _viewport.set(
x.x,
x.y,
x.z,
x.w );
28890 _viewport.set(
x,
y, width, height );
28894 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor() );
28898 this.getScissor =
function ( target ) {
28900 return target.copy( _scissor );
28904 this.setScissor =
function (
x,
y, width, height ) {
28906 if (
x.isVector4 ) {
28908 _scissor.set(
x.x,
x.y,
x.z,
x.w );
28912 _scissor.set(
x,
y, width, height );
28916 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor() );
28920 this.getScissorTest =
function () {
28922 return _scissorTest;
28926 this.setScissorTest =
function ( boolean ) {
28928 state.setScissorTest( _scissorTest =
boolean );
28932 this.setOpaqueSort =
function ( method ) {
28934 _opaqueSort = method;
28938 this.setTransparentSort =
function ( method ) {
28940 _transparentSort = method;
28946 this.getClearColor =
function ( target ) {
28948 return target.copy( background.getClearColor() );
28952 this.setClearColor =
function () {
28954 background.setClearColor.apply( background, arguments );
28958 this.getClearAlpha =
function () {
28960 return background.getClearAlpha();
28964 this.setClearAlpha =
function () {
28966 background.setClearAlpha.apply( background, arguments );
28970 this.clear =
function ( color =
true, depth =
true, stencil = true ) {
28977 let isIntegerFormat =
false;
28978 if ( _currentRenderTarget !==
null ) {
28980 const targetFormat = _currentRenderTarget.texture.format;
28981 isIntegerFormat = targetFormat === RGBAIntegerFormat ||
28982 targetFormat === RGIntegerFormat ||
28983 targetFormat === RedIntegerFormat;
28989 if ( isIntegerFormat ) {
28991 const targetType = _currentRenderTarget.texture.type;
28995 targetType === UnsignedInt248Type ||
28999 const clearColor = background.getClearColor();
29000 const a = background.getClearAlpha();
29001 const r = clearColor.r;
29002 const g = clearColor.g;
29003 const b = clearColor.b;
29005 if ( isUnsignedType ) {
29007 uintClearColor[ 0 ] =
r;
29008 uintClearColor[ 1 ] =
g;
29009 uintClearColor[ 2 ] =
b;
29010 uintClearColor[ 3 ] =
a;
29011 _gl.clearBufferuiv( _gl.COLOR, 0, uintClearColor );
29015 intClearColor[ 0 ] =
r;
29016 intClearColor[ 1 ] =
g;
29017 intClearColor[ 2 ] =
b;
29018 intClearColor[ 3 ] =
a;
29019 _gl.clearBufferiv( _gl.COLOR, 0, intClearColor );
29025 bits |= _gl.COLOR_BUFFER_BIT;
29031 if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT;
29034 bits |= _gl.STENCIL_BUFFER_BIT;
29035 this.state.buffers.stencil.setMask( 0xffffffff );
29043 this.clearColor =
function () {
29045 this.clear(
true,
false,
false );
29049 this.clearDepth =
function () {
29051 this.clear(
false,
true,
false );
29055 this.clearStencil =
function () {
29057 this.clear(
false,
false,
true );
29065 canvas.removeEventListener(
'webglcontextlost', onContextLost,
false );
29066 canvas.removeEventListener(
'webglcontextrestored', onContextRestore,
false );
29067 canvas.removeEventListener(
'webglcontextcreationerror', onContextCreationError,
false );
29069 renderLists.dispose();
29070 renderStates.dispose();
29071 properties.dispose();
29072 cubemaps.dispose();
29073 cubeuvmaps.dispose();
29075 bindingStates.dispose();
29076 uniformsGroups.dispose();
29077 programCache.dispose();
29081 xr.removeEventListener(
'sessionstart', onXRSessionStart );
29082 xr.removeEventListener(
'sessionend', onXRSessionEnd );
29084 if ( _transmissionRenderTarget ) {
29086 _transmissionRenderTarget.dispose();
29087 _transmissionRenderTarget =
null;
29097 function onContextLost( event ) {
29099 event.preventDefault();
29101 console.log(
'THREE.WebGLRenderer: Context Lost.' );
29103 _isContextLost =
true;
29107 function onContextRestore( ) {
29109 console.log(
'THREE.WebGLRenderer: Context Restored.' );
29111 _isContextLost =
false;
29113 const infoAutoReset = info.autoReset;
29114 const shadowMapEnabled = shadowMap.enabled;
29115 const shadowMapAutoUpdate = shadowMap.autoUpdate;
29116 const shadowMapNeedsUpdate = shadowMap.needsUpdate;
29117 const shadowMapType = shadowMap.type;
29121 info.autoReset = infoAutoReset;
29122 shadowMap.enabled = shadowMapEnabled;
29123 shadowMap.autoUpdate = shadowMapAutoUpdate;
29124 shadowMap.needsUpdate = shadowMapNeedsUpdate;
29125 shadowMap.type = shadowMapType;
29129 function onContextCreationError( event ) {
29131 console.error(
'THREE.WebGLRenderer: A WebGL context could not be created. Reason: ', event.statusMessage );
29135 function onMaterialDispose( event ) {
29137 const material =
event.target;
29139 material.removeEventListener(
'dispose', onMaterialDispose );
29141 deallocateMaterial( material );
29147 function deallocateMaterial( material ) {
29149 releaseMaterialProgramReferences( material );
29151 properties.remove( material );
29156 function releaseMaterialProgramReferences( material ) {
29158 const programs = properties.get( material ).programs;
29162 programs.forEach(
function ( program ) {
29164 programCache.releaseProgram( program );
29168 if ( material.isShaderMaterial ) {
29170 programCache.releaseShaderCache( material );
29180 this.renderBufferDirect =
function ( camera, scene, geometry, material,
object, group ) {
29182 if ( scene ===
null ) scene = _emptyScene;
29184 const frontFaceCW = (
object.isMesh &&
object.matrixWorld.determinant() < 0 );
29186 const program = setProgram( camera, scene, geometry, material,
object );
29188 state.setMaterial( material, frontFaceCW );
29192 let index = geometry.index;
29193 let rangeFactor = 1;
29195 if ( material.wireframe ===
true ) {
29197 index = geometries.getWireframeAttribute( geometry );
29207 const drawRange = geometry.drawRange;
29208 const position = geometry.attributes.position;
29210 let drawStart = drawRange.start * rangeFactor;
29211 let drawEnd = ( drawRange.start + drawRange.count ) * rangeFactor;
29213 if ( group !==
null ) {
29215 drawStart =
Math.max( drawStart, group.start * rangeFactor );
29216 drawEnd =
Math.min( drawEnd, ( group.start + group.count ) * rangeFactor );
29220 if ( index !==
null ) {
29222 drawStart =
Math.max( drawStart, 0 );
29223 drawEnd =
Math.min( drawEnd, index.count );
29227 drawStart =
Math.max( drawStart, 0 );
29232 const drawCount = drawEnd - drawStart;
29234 if ( drawCount < 0 || drawCount === Infinity )
return;
29238 bindingStates.setup(
object, material, program, geometry, index );
29241 let renderer = bufferRenderer;
29243 if ( index !==
null ) {
29245 attribute = attributes.get( index );
29247 renderer = indexedBufferRenderer;
29248 renderer.setIndex( attribute );
29254 if (
object.isMesh ) {
29256 if ( material.wireframe ===
true ) {
29258 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() );
29259 renderer.setMode( _gl.LINES );
29263 renderer.setMode( _gl.TRIANGLES );
29267 }
else if (
object.isLine ) {
29269 let lineWidth = material.linewidth;
29271 if ( lineWidth ===
undefined ) lineWidth = 1;
29273 state.setLineWidth( lineWidth * getTargetPixelRatio() );
29275 if (
object.isLineSegments ) {
29277 renderer.setMode( _gl.LINES );
29279 }
else if (
object.isLineLoop ) {
29281 renderer.setMode( _gl.LINE_LOOP );
29285 renderer.setMode( _gl.LINE_STRIP );
29289 }
else if (
object.isPoints ) {
29291 renderer.setMode( _gl.POINTS );
29293 }
else if (
object.isSprite ) {
29295 renderer.setMode( _gl.TRIANGLES );
29299 if (
object.isBatchedMesh ) {
29301 renderer.renderMultiDraw(
object._multiDrawStarts,
object._multiDrawCounts,
object._multiDrawCount );
29303 }
else if (
object.isInstancedMesh ) {
29305 renderer.renderInstances( drawStart, drawCount,
object.count );
29307 }
else if ( geometry.isInstancedBufferGeometry ) {
29309 const maxInstanceCount = geometry._maxInstanceCount !==
undefined ? geometry._maxInstanceCount : Infinity;
29310 const instanceCount =
Math.min( geometry.instanceCount, maxInstanceCount );
29312 renderer.renderInstances( drawStart, drawCount, instanceCount );
29316 renderer.render( drawStart, drawCount );
29324 function prepareMaterial( material, scene,
object ) {
29326 if ( material.transparent ===
true && material.side ===
DoubleSide && material.forceSinglePass ===
false ) {
29329 material.needsUpdate =
true;
29330 getProgram( material, scene,
object );
29333 material.needsUpdate =
true;
29334 getProgram( material, scene,
object );
29340 getProgram( material, scene,
object );
29346 this.compile =
function ( scene, camera, targetScene = null ) {
29348 if ( targetScene ===
null ) targetScene = scene;
29350 currentRenderState = renderStates.get( targetScene );
29351 currentRenderState.init();
29353 renderStateStack.push( currentRenderState );
29357 targetScene.traverseVisible(
function (
object ) {
29359 if (
object.isLight &&
object.layers.test( camera.layers ) ) {
29361 currentRenderState.pushLight(
object );
29363 if (
object.castShadow ) {
29365 currentRenderState.pushShadow(
object );
29373 if ( scene !== targetScene ) {
29375 scene.traverseVisible(
function (
object ) {
29377 if (
object.isLight &&
object.layers.test( camera.layers ) ) {
29379 currentRenderState.pushLight(
object );
29381 if (
object.castShadow ) {
29383 currentRenderState.pushShadow(
object );
29393 currentRenderState.setupLights( _this._useLegacyLights );
29397 const materials =
new Set();
29399 scene.traverse(
function (
object ) {
29401 const material =
object.material;
29405 if (
Array.isArray( material ) ) {
29407 for ( let
i = 0;
i < material.length;
i ++ ) {
29409 const material2 = material[
i ];
29411 prepareMaterial( material2, targetScene,
object );
29412 materials.add( material2 );
29418 prepareMaterial( material, targetScene,
object );
29419 materials.add( material );
29427 renderStateStack.pop();
29428 currentRenderState =
null;
29436 this.compileAsync =
function ( scene, camera, targetScene = null ) {
29438 const materials = this.compile( scene, camera, targetScene );
29443 return new Promise( ( resolve ) => {
29445 function checkMaterialsReady() {
29447 materials.forEach(
function ( material ) {
29449 const materialProperties = properties.get( material );
29450 const program = materialProperties.currentProgram;
29452 if ( program.isReady() ) {
29455 materials.delete( material );
29463 if ( materials.size === 0 ) {
29472 setTimeout( checkMaterialsReady, 10 );
29476 if ( extensions.get(
'KHR_parallel_shader_compile' ) !==
null ) {
29481 checkMaterialsReady();
29488 setTimeout( checkMaterialsReady, 10 );
29498 let onAnimationFrameCallback =
null;
29500 function onAnimationFrame( time ) {
29502 if ( onAnimationFrameCallback ) onAnimationFrameCallback( time );
29506 function onXRSessionStart() {
29512 function onXRSessionEnd() {
29518 const animation =
new WebGLAnimation();
29519 animation.setAnimationLoop( onAnimationFrame );
29521 if ( typeof
self !==
'undefined' ) animation.setContext(
self );
29523 this.setAnimationLoop =
function ( callback ) {
29525 onAnimationFrameCallback = callback;
29526 xr.setAnimationLoop( callback );
29528 ( callback === null ) ? animation.stop() : animation.start();
29532 xr.addEventListener(
'sessionstart', onXRSessionStart );
29533 xr.addEventListener(
'sessionend', onXRSessionEnd );
29537 this.render =
function ( scene, camera ) {
29539 if ( camera !==
undefined && camera.isCamera !==
true ) {
29541 console.error(
'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
29546 if ( _isContextLost ===
true )
return;
29550 if ( scene.matrixWorldAutoUpdate ===
true ) scene.updateMatrixWorld();
29554 if ( camera.parent ===
null && camera.matrixWorldAutoUpdate ===
true ) camera.updateMatrixWorld();
29556 if ( xr.enabled ===
true && xr.isPresenting ===
true ) {
29558 if ( xr.cameraAutoUpdate ===
true ) xr.updateCamera( camera );
29560 camera = xr.getCamera();
29565 if ( scene.isScene ===
true ) scene.onBeforeRender( _this, scene, camera, _currentRenderTarget );
29567 currentRenderState = renderStates.get( scene, renderStateStack.length );
29568 currentRenderState.init();
29570 renderStateStack.push( currentRenderState );
29572 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
29573 _frustum.setFromProjectionMatrix( _projScreenMatrix );
29575 _localClippingEnabled = this.localClippingEnabled;
29576 _clippingEnabled = clipping.init( this.clippingPlanes, _localClippingEnabled );
29578 currentRenderList = renderLists.get( scene, renderListStack.length );
29579 currentRenderList.init();
29581 renderListStack.push( currentRenderList );
29583 projectObject( scene, camera, 0, _this.sortObjects );
29585 currentRenderList.finish();
29587 if ( _this.sortObjects ===
true ) {
29589 currentRenderList.sort( _opaqueSort, _transparentSort );
29595 this.info.render.frame ++;
29597 if ( _clippingEnabled ===
true ) clipping.beginShadows();
29599 const shadowsArray = currentRenderState.state.shadowsArray;
29601 shadowMap.render( shadowsArray, scene, camera );
29603 if ( _clippingEnabled ===
true ) clipping.endShadows();
29607 if ( this.info.autoReset ===
true ) this.info.reset();
29612 background.render( currentRenderList, scene );
29616 currentRenderState.setupLights( _this._useLegacyLights );
29618 if ( camera.isArrayCamera ) {
29620 const cameras = camera.cameras;
29622 for ( let
i = 0,
l = cameras.length;
i <
l;
i ++ ) {
29624 const camera2 = cameras[
i ];
29626 renderScene( currentRenderList, scene, camera2, camera2.viewport );
29632 renderScene( currentRenderList, scene, camera );
29638 if ( _currentRenderTarget !==
null ) {
29642 textures.updateMultisampleRenderTarget( _currentRenderTarget );
29646 textures.updateRenderTargetMipmap( _currentRenderTarget );
29652 if ( scene.isScene ===
true ) scene.onAfterRender( _this, scene, camera );
29656 bindingStates.resetDefaultState();
29657 _currentMaterialId = - 1;
29658 _currentCamera =
null;
29660 renderStateStack.pop();
29662 if ( renderStateStack.length > 0 ) {
29664 currentRenderState = renderStateStack[ renderStateStack.length - 1 ];
29668 currentRenderState =
null;
29672 renderListStack.pop();
29674 if ( renderListStack.length > 0 ) {
29676 currentRenderList = renderListStack[ renderListStack.length - 1 ];
29680 currentRenderList =
null;
29686 function projectObject(
object, camera, groupOrder, sortObjects ) {
29688 if (
object.visible ===
false )
return;
29690 const visible =
object.layers.test( camera.layers );
29694 if (
object.isGroup ) {
29696 groupOrder =
object.renderOrder;
29698 }
else if (
object.isLOD ) {
29700 if (
object.autoUpdate ===
true )
object.update( camera );
29702 }
else if (
object.isLight ) {
29704 currentRenderState.pushLight(
object );
29706 if (
object.castShadow ) {
29708 currentRenderState.pushShadow(
object );
29712 }
else if (
object.isSprite ) {
29714 if ( !
object.frustumCulled || _frustum.intersectsSprite(
object ) ) {
29716 if ( sortObjects ) {
29718 _vector3.setFromMatrixPosition(
object.matrixWorld )
29719 .applyMatrix4( _projScreenMatrix );
29723 const geometry = objects.update(
object );
29724 const material =
object.material;
29726 if ( material.visible ) {
29728 currentRenderList.push(
object, geometry, material, groupOrder, _vector3.z,
null );
29734 }
else if (
object.isMesh ||
object.isLine ||
object.isPoints ) {
29736 if ( !
object.frustumCulled || _frustum.intersectsObject(
object ) ) {
29738 const geometry = objects.update(
object );
29739 const material =
object.material;
29741 if ( sortObjects ) {
29743 if (
object.boundingSphere !==
undefined ) {
29745 if (
object.boundingSphere ===
null )
object.computeBoundingSphere();
29746 _vector3.copy(
object.boundingSphere.center );
29750 if ( geometry.boundingSphere ===
null ) geometry.computeBoundingSphere();
29751 _vector3.copy( geometry.boundingSphere.center );
29756 .applyMatrix4(
object.matrixWorld )
29757 .applyMatrix4( _projScreenMatrix );
29761 if (
Array.isArray( material ) ) {
29763 const groups = geometry.groups;
29765 for ( let
i = 0,
l = groups.length;
i <
l;
i ++ ) {
29767 const group = groups[
i ];
29768 const groupMaterial = material[ group.materialIndex ];
29770 if ( groupMaterial && groupMaterial.visible ) {
29772 currentRenderList.push(
object, geometry, groupMaterial, groupOrder, _vector3.z, group );
29778 }
else if ( material.visible ) {
29780 currentRenderList.push(
object, geometry, material, groupOrder, _vector3.z,
null );
29790 const children =
object.children;
29792 for ( let
i = 0,
l = children.length;
i <
l;
i ++ ) {
29794 projectObject( children[
i ], camera, groupOrder, sortObjects );
29800 function renderScene( currentRenderList, scene, camera, viewport ) {
29802 const opaqueObjects = currentRenderList.opaque;
29803 const transmissiveObjects = currentRenderList.transmissive;
29804 const transparentObjects = currentRenderList.transparent;
29806 currentRenderState.setupLightsView( camera );
29808 if ( _clippingEnabled ===
true ) clipping.setGlobalState( _this.clippingPlanes, camera );
29810 if ( transmissiveObjects.length > 0 ) renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera );
29812 if ( viewport ) state.viewport( _currentViewport.copy( viewport ) );
29814 if ( opaqueObjects.length > 0 ) renderObjects( opaqueObjects, scene, camera );
29815 if ( transmissiveObjects.length > 0 ) renderObjects( transmissiveObjects, scene, camera );
29816 if ( transparentObjects.length > 0 ) renderObjects( transparentObjects, scene, camera );
29820 state.buffers.depth.setTest(
true );
29821 state.buffers.depth.setMask(
true );
29822 state.buffers.color.setMask(
true );
29824 state.setPolygonOffset(
false );
29828 function renderTransmissionPass( opaqueObjects, transmissiveObjects, scene, camera ) {
29830 const overrideMaterial = scene.isScene ===
true ? scene.overrideMaterial :
null;
29832 if ( overrideMaterial !==
null ) {
29838 const isWebGL2 = capabilities.isWebGL2;
29840 if ( _transmissionRenderTarget ===
null ) {
29843 generateMipmaps:
true,
29844 type: extensions.has(
'EXT_color_buffer_half_float' ) ? HalfFloatType :
UnsignedByteType,
29845 minFilter: LinearMipmapLinearFilter,
29846 samples: ( isWebGL2 ) ? 4 : 0
29861 _this.getDrawingBufferSize( _vector2 );
29865 _transmissionRenderTarget.setSize( _vector2.x, _vector2.y );
29869 _transmissionRenderTarget.setSize( floorPowerOfTwo( _vector2.x ), floorPowerOfTwo( _vector2.y ) );
29875 const currentRenderTarget = _this.getRenderTarget();
29876 _this.setRenderTarget( _transmissionRenderTarget );
29878 _this.getClearColor( _currentClearColor );
29879 _currentClearAlpha = _this.getClearAlpha();
29880 if ( _currentClearAlpha < 1 ) _this.setClearColor( 0xffffff, 0.5 );
29886 const currentToneMapping = _this.toneMapping;
29887 _this.toneMapping = NoToneMapping;
29889 renderObjects( opaqueObjects, scene, camera );
29891 textures.updateMultisampleRenderTarget( _transmissionRenderTarget );
29892 textures.updateRenderTargetMipmap( _transmissionRenderTarget );
29894 let renderTargetNeedsUpdate =
false;
29896 for ( let
i = 0,
l = transmissiveObjects.length;
i <
l;
i ++ ) {
29898 const renderItem = transmissiveObjects[ i ];
29900 const object = renderItem.object;
29901 const geometry = renderItem.geometry;
29902 const material = renderItem.material;
29903 const group = renderItem.group;
29905 if ( material.side === DoubleSide && object.layers.test( camera.layers ) ) {
29907 const currentSide = material.side;
29909 material.side = BackSide;
29910 material.needsUpdate = true;
29912 renderObject( object, scene, camera, geometry, material, group );
29914 material.side = currentSide;
29915 material.needsUpdate = true;
29917 renderTargetNeedsUpdate = true;
29923 if ( renderTargetNeedsUpdate ===
true ) {
29925 textures.updateMultisampleRenderTarget( _transmissionRenderTarget );
29926 textures.updateRenderTargetMipmap( _transmissionRenderTarget );
29930 _this.setRenderTarget( currentRenderTarget );
29932 _this.setClearColor( _currentClearColor, _currentClearAlpha );
29934 _this.toneMapping = currentToneMapping;
29938 function renderObjects( renderList, scene, camera ) {
29940 const overrideMaterial = scene.isScene ===
true ? scene.overrideMaterial :
null;
29942 for ( let
i = 0,
l = renderList.length;
i <
l;
i ++ ) {
29944 const renderItem = renderList[
i ];
29946 const object = renderItem.object;
29947 const geometry = renderItem.geometry;
29948 const material = overrideMaterial ===
null ? renderItem.material : overrideMaterial;
29949 const group = renderItem.group;
29951 if (
object.layers.test( camera.layers ) ) {
29953 renderObject(
object, scene, camera, geometry, material, group );
29961 function renderObject(
object, scene, camera, geometry, material, group ) {
29963 object.onBeforeRender( _this, scene, camera, geometry, material, group );
29965 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse,
object.matrixWorld );
29966 object.normalMatrix.getNormalMatrix(
object.modelViewMatrix );
29968 material.onBeforeRender( _this, scene, camera, geometry,
object, group );
29970 if ( material.transparent ===
true && material.side ===
DoubleSide && material.forceSinglePass ===
false ) {
29973 material.needsUpdate =
true;
29974 _this.renderBufferDirect( camera, scene, geometry, material,
object, group );
29977 material.needsUpdate =
true;
29978 _this.renderBufferDirect( camera, scene, geometry, material,
object, group );
29984 _this.renderBufferDirect( camera, scene, geometry, material,
object, group );
29988 object.onAfterRender( _this, scene, camera, geometry, material, group );
29992 function getProgram( material, scene,
object ) {
29994 if ( scene.isScene !==
true ) scene = _emptyScene;
29996 const materialProperties = properties.get( material );
29998 const lights = currentRenderState.state.lights;
29999 const shadowsArray = currentRenderState.state.shadowsArray;
30001 const lightsStateVersion = lights.state.version;
30003 const parameters = programCache.getParameters( material, lights.state, shadowsArray, scene,
object );
30004 const programCacheKey = programCache.getProgramCacheKey( parameters );
30006 let programs = materialProperties.programs;
30010 materialProperties.environment = material.isMeshStandardMaterial ? scene.environment :
null;
30011 materialProperties.fog = scene.fog;
30012 materialProperties.envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).
get( material.envMap || materialProperties.environment );
30018 material.addEventListener(
'dispose', onMaterialDispose );
30020 programs =
new Map();
30021 materialProperties.programs = programs;
30025 let program = programs.get( programCacheKey );
30031 if ( materialProperties.currentProgram === program && materialProperties.lightsStateVersion === lightsStateVersion ) {
30033 updateCommonMaterialProperties( material, parameters );
30041 parameters.uniforms = programCache.getUniforms( material );
30043 material.onBuild(
object, parameters, _this );
30045 material.onBeforeCompile( parameters, _this );
30047 program = programCache.acquireProgram( parameters, programCacheKey );
30048 programs.set( programCacheKey, program );
30050 materialProperties.uniforms = parameters.uniforms;
30054 const uniforms = materialProperties.uniforms;
30056 if ( ( ! material.isShaderMaterial && ! material.isRawShaderMaterial ) || material.clipping ===
true ) {
30058 uniforms.clippingPlanes = clipping.uniform;
30062 updateCommonMaterialProperties( material, parameters );
30066 materialProperties.needsLights = materialNeedsLights( material );
30067 materialProperties.lightsStateVersion = lightsStateVersion;
30069 if ( materialProperties.needsLights ) {
30073 uniforms.ambientLightColor.value = lights.state.ambient;
30074 uniforms.lightProbe.value = lights.state.probe;
30075 uniforms.directionalLights.value = lights.state.directional;
30076 uniforms.directionalLightShadows.value = lights.state.directionalShadow;
30077 uniforms.spotLights.value = lights.state.spot;
30078 uniforms.spotLightShadows.value = lights.state.spotShadow;
30079 uniforms.rectAreaLights.value = lights.state.rectArea;
30080 uniforms.ltc_1.value = lights.state.rectAreaLTC1;
30081 uniforms.ltc_2.value = lights.state.rectAreaLTC2;
30082 uniforms.pointLights.value = lights.state.point;
30083 uniforms.pointLightShadows.value = lights.state.pointShadow;
30084 uniforms.hemisphereLights.value = lights.state.hemi;
30086 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap;
30087 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix;
30088 uniforms.spotShadowMap.value = lights.state.spotShadowMap;
30089 uniforms.spotLightMatrix.value = lights.state.spotLightMatrix;
30090 uniforms.spotLightMap.value = lights.state.spotLightMap;
30091 uniforms.pointShadowMap.value = lights.state.pointShadowMap;
30092 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix;
30097 materialProperties.currentProgram = program;
30098 materialProperties.uniformsList =
null;
30104 function getUniformList( materialProperties ) {
30106 if ( materialProperties.uniformsList ===
null ) {
30108 const progUniforms = materialProperties.currentProgram.getUniforms();
30109 materialProperties.uniformsList = WebGLUniforms.seqWithValue( progUniforms.seq, materialProperties.uniforms );
30113 return materialProperties.uniformsList;
30117 function updateCommonMaterialProperties( material, parameters ) {
30119 const materialProperties = properties.get( material );
30121 materialProperties.outputColorSpace = parameters.outputColorSpace;
30122 materialProperties.batching = parameters.batching;
30123 materialProperties.instancing = parameters.instancing;
30124 materialProperties.instancingColor = parameters.instancingColor;
30125 materialProperties.skinning = parameters.skinning;
30126 materialProperties.morphTargets = parameters.morphTargets;
30127 materialProperties.morphNormals = parameters.morphNormals;
30128 materialProperties.morphColors = parameters.morphColors;
30129 materialProperties.morphTargetsCount = parameters.morphTargetsCount;
30130 materialProperties.numClippingPlanes = parameters.numClippingPlanes;
30131 materialProperties.numIntersection = parameters.numClipIntersection;
30132 materialProperties.vertexAlphas = parameters.vertexAlphas;
30133 materialProperties.vertexTangents = parameters.vertexTangents;
30134 materialProperties.toneMapping = parameters.toneMapping;
30138 function setProgram( camera, scene, geometry, material,
object ) {
30140 if ( scene.isScene !==
true ) scene = _emptyScene;
30142 textures.resetTextureUnits();
30144 const fog = scene.fog;
30145 const environment = material.isMeshStandardMaterial ? scene.environment :
null;
30146 const colorSpace = ( _currentRenderTarget === null ) ? _this.outputColorSpace : ( _currentRenderTarget.isXRRenderTarget === true ? _currentRenderTarget.texture.colorSpace : LinearSRGBColorSpace );
30147 const envMap = ( material.isMeshStandardMaterial ? cubeuvmaps : cubemaps ).get( material.envMap || environment );
30148 const vertexAlphas = material.vertexColors ===
true && !! geometry.attributes.color && geometry.attributes.color.itemSize === 4;
30149 const vertexTangents = !! geometry.attributes.tangent && ( !! material.normalMap || material.anisotropy > 0 );
30150 const morphTargets = !! geometry.morphAttributes.position;
30151 const morphNormals = !! geometry.morphAttributes.normal;
30152 const morphColors = !! geometry.morphAttributes.color;
30154 let toneMapping = NoToneMapping;
30156 if ( material.toneMapped ) {
30158 if ( _currentRenderTarget === null || _currentRenderTarget.isXRRenderTarget === true ) {
30160 toneMapping = _this.toneMapping;
30166 const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color;
30167 const morphTargetsCount = ( morphAttribute !==
undefined ) ? morphAttribute.length : 0;
30169 const materialProperties = properties.get( material );
30170 const lights = currentRenderState.state.lights;
30172 if ( _clippingEnabled ===
true ) {
30174 if ( _localClippingEnabled ===
true || camera !== _currentCamera ) {
30177 camera === _currentCamera &&
30178 material.id === _currentMaterialId;
30183 clipping.setState( material, camera, useCache );
30191 let needsProgramChange =
false;
30193 if ( material.version === materialProperties.__version ) {
30195 if ( materialProperties.needsLights && ( materialProperties.lightsStateVersion !== lights.state.version ) ) {
30197 needsProgramChange = true;
30199 }
else if ( materialProperties.outputColorSpace !== colorSpace ) {
30201 needsProgramChange = true;
30203 }
else if (
object.isBatchedMesh && materialProperties.batching ===
false ) {
30205 needsProgramChange = true;
30207 }
else if ( !
object.isBatchedMesh && materialProperties.batching ===
true ) {
30209 needsProgramChange = true;
30211 }
else if (
object.isInstancedMesh && materialProperties.instancing ===
false ) {
30213 needsProgramChange = true;
30215 }
else if ( !
object.isInstancedMesh && materialProperties.instancing ===
true ) {
30217 needsProgramChange = true;
30219 }
else if (
object.isSkinnedMesh && materialProperties.skinning ===
false ) {
30221 needsProgramChange = true;
30223 }
else if ( !
object.isSkinnedMesh && materialProperties.skinning ===
true ) {
30225 needsProgramChange = true;
30227 }
else if (
object.isInstancedMesh && materialProperties.instancingColor ===
true &&
object.instanceColor ===
null ) {
30229 needsProgramChange = true;
30231 }
else if (
object.isInstancedMesh && materialProperties.instancingColor ===
false &&
object.instanceColor !==
null ) {
30233 needsProgramChange = true;
30235 }
else if ( materialProperties.envMap !== envMap ) {
30237 needsProgramChange = true;
30239 }
else if ( material.fog ===
true && materialProperties.fog !== fog ) {
30241 needsProgramChange = true;
30243 }
else if ( materialProperties.numClippingPlanes !==
undefined &&
30244 ( materialProperties.numClippingPlanes !== clipping.numPlanes ||
30245 materialProperties.numIntersection !== clipping.numIntersection ) ) {
30247 needsProgramChange = true;
30249 }
else if ( materialProperties.vertexAlphas !== vertexAlphas ) {
30251 needsProgramChange = true;
30253 }
else if ( materialProperties.vertexTangents !== vertexTangents ) {
30255 needsProgramChange = true;
30257 }
else if ( materialProperties.morphTargets !== morphTargets ) {
30259 needsProgramChange = true;
30261 }
else if ( materialProperties.morphNormals !== morphNormals ) {
30263 needsProgramChange = true;
30265 }
else if ( materialProperties.morphColors !== morphColors ) {
30267 needsProgramChange = true;
30269 }
else if ( materialProperties.toneMapping !== toneMapping ) {
30271 needsProgramChange = true;
30273 }
else if ( capabilities.isWebGL2 ===
true && materialProperties.morphTargetsCount !== morphTargetsCount ) {
30275 needsProgramChange = true;
30281 needsProgramChange =
true;
30282 materialProperties.__version = material.version;
30288 let program = materialProperties.currentProgram;
30290 if ( needsProgramChange ===
true ) {
30292 program = getProgram( material, scene,
object );
30296 let refreshProgram =
false;
30297 let refreshMaterial =
false;
30298 let refreshLights =
false;
30300 const p_uniforms = program.getUniforms(),
30301 m_uniforms = materialProperties.uniforms;
30303 if ( state.useProgram( program.program ) ) {
30305 refreshProgram = true;
30306 refreshMaterial = true;
30307 refreshLights = true;
30311 if ( material.id !== _currentMaterialId ) {
30313 _currentMaterialId = material.id;
30315 refreshMaterial = true;
30319 if ( refreshProgram || _currentCamera !== camera ) {
30323 p_uniforms.setValue( _gl,
'projectionMatrix', camera.projectionMatrix );
30324 p_uniforms.setValue( _gl,
'viewMatrix', camera.matrixWorldInverse );
30326 const uCamPos = p_uniforms.map.cameraPosition;
30330 uCamPos.setValue( _gl, _vector3.setFromMatrixPosition( camera.matrixWorld ) );
30334 if ( capabilities.logarithmicDepthBuffer ) {
30336 p_uniforms.setValue( _gl,
'logDepthBufFC',
30337 2.0 / (
Math.log( camera.far + 1.0 ) /
Math.LN2 ) );
30343 if ( material.isMeshPhongMaterial ||
30344 material.isMeshToonMaterial ||
30345 material.isMeshLambertMaterial ||
30346 material.isMeshBasicMaterial ||
30347 material.isMeshStandardMaterial ||
30348 material.isShaderMaterial ) {
30350 p_uniforms.setValue( _gl,
'isOrthographic', camera.isOrthographicCamera ===
true );
30354 if ( _currentCamera !== camera ) {
30356 _currentCamera = camera;
30362 refreshMaterial =
true;
30363 refreshLights =
true;
30373 if (
object.isSkinnedMesh ) {
30375 p_uniforms.setOptional( _gl,
object,
'bindMatrix' );
30376 p_uniforms.setOptional( _gl,
object,
'bindMatrixInverse' );
30378 const skeleton =
object.skeleton;
30382 if ( capabilities.floatVertexTextures ) {
30384 if ( skeleton.boneTexture ===
null ) skeleton.computeBoneTexture();
30386 p_uniforms.setValue( _gl,
'boneTexture', skeleton.boneTexture, textures );
30390 console.warn(
'THREE.WebGLRenderer: SkinnedMesh can only be used with WebGL 2. With WebGL 1 OES_texture_float and vertex textures support is required.' );
30398 if (
object.isBatchedMesh ) {
30400 p_uniforms.setOptional( _gl,
object,
'batchingTexture' );
30401 p_uniforms.setValue( _gl,
'batchingTexture',
object._matricesTexture, textures );
30405 const morphAttributes = geometry.morphAttributes;
30407 if ( morphAttributes.position !==
undefined || morphAttributes.normal !==
undefined || ( morphAttributes.color !==
undefined && capabilities.isWebGL2 ===
true ) ) {
30409 morphtargets.update( object, geometry, program );
30413 if ( refreshMaterial || materialProperties.receiveShadow !==
object.receiveShadow ) {
30415 materialProperties.receiveShadow = object.receiveShadow;
30416 p_uniforms.setValue( _gl,
'receiveShadow', object.receiveShadow );
30422 if ( material.isMeshGouraudMaterial && material.envMap !==
null ) {
30424 m_uniforms.envMap.value = envMap;
30426 m_uniforms.flipEnvMap.value = ( envMap.isCubeTexture && envMap.isRenderTargetTexture === false ) ? - 1 : 1;
30430 if ( refreshMaterial ) {
30432 p_uniforms.setValue( _gl,
'toneMappingExposure', _this.toneMappingExposure );
30434 if ( materialProperties.needsLights ) {
30445 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights );
30451 if ( fog && material.fog ===
true ) {
30453 materials.refreshFogUniforms( m_uniforms, fog );
30457 materials.refreshMaterialUniforms( m_uniforms, material, _pixelRatio, _height, _transmissionRenderTarget );
30459 WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
30463 if ( material.isShaderMaterial && material.uniformsNeedUpdate ===
true ) {
30465 WebGLUniforms.upload( _gl, getUniformList( materialProperties ), m_uniforms, textures );
30466 material.uniformsNeedUpdate = false;
30470 if ( material.isSpriteMaterial ) {
30472 p_uniforms.setValue( _gl,
'center', object.center );
30478 p_uniforms.setValue( _gl,
'modelViewMatrix',
object.modelViewMatrix );
30479 p_uniforms.setValue( _gl,
'normalMatrix',
object.normalMatrix );
30480 p_uniforms.setValue( _gl,
'modelMatrix',
object.matrixWorld );
30484 if ( material.isShaderMaterial || material.isRawShaderMaterial ) {
30486 const groups = material.uniformsGroups;
30488 for ( let i = 0, l = groups.length; i < l; i ++ ) {
30490 if ( capabilities.isWebGL2 ) {
30492 const group = groups[ i ];
30494 uniformsGroups.update( group, program );
30495 uniformsGroups.bind( group, program );
30499 console.warn(
'THREE.WebGLRenderer: Uniform Buffer Objects can only be used with WebGL 2.' );
30513 function markUniformsLightsNeedsUpdate( uniforms, value ) {
30515 uniforms.ambientLightColor.needsUpdate = value;
30516 uniforms.lightProbe.needsUpdate = value;
30518 uniforms.directionalLights.needsUpdate = value;
30519 uniforms.directionalLightShadows.needsUpdate = value;
30520 uniforms.pointLights.needsUpdate = value;
30521 uniforms.pointLightShadows.needsUpdate = value;
30522 uniforms.spotLights.needsUpdate = value;
30523 uniforms.spotLightShadows.needsUpdate = value;
30524 uniforms.rectAreaLights.needsUpdate = value;
30525 uniforms.hemisphereLights.needsUpdate = value;
30529 function materialNeedsLights( material ) {
30531 return material.isMeshLambertMaterial || material.isMeshToonMaterial || material.isMeshPhongMaterial ||
30532 material.isMeshStandardMaterial || material.isShadowMaterial ||
30533 ( material.isShaderMaterial && material.lights === true );
30537 this.getActiveCubeFace =
function () {
30539 return _currentActiveCubeFace;
30543 this.getActiveMipmapLevel =
function () {
30545 return _currentActiveMipmapLevel;
30549 this.getRenderTarget =
function () {
30551 return _currentRenderTarget;
30555 this.setRenderTargetTextures =
function ( renderTarget, colorTexture, depthTexture ) {
30557 properties.get( renderTarget.texture ).__webglTexture = colorTexture;
30558 properties.get( renderTarget.depthTexture ).__webglTexture = depthTexture;
30560 const renderTargetProperties = properties.get( renderTarget );
30561 renderTargetProperties.__hasExternalTextures =
true;
30563 if ( renderTargetProperties.__hasExternalTextures ) {
30565 renderTargetProperties.__autoAllocateDepthBuffer = depthTexture ===
undefined;
30567 if ( ! renderTargetProperties.__autoAllocateDepthBuffer ) {
30571 if ( extensions.has(
'WEBGL_multisampled_render_to_texture' ) ===
true ) {
30573 console.warn(
'THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided' );
30574 renderTargetProperties.__useRenderToTexture =
false;
30584 this.setRenderTargetFramebuffer =
function ( renderTarget, defaultFramebuffer ) {
30586 const renderTargetProperties = properties.get( renderTarget );
30587 renderTargetProperties.__webglFramebuffer = defaultFramebuffer;
30588 renderTargetProperties.__useDefaultFramebuffer = defaultFramebuffer ===
undefined;
30592 this.setRenderTarget =
function ( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) {
30594 _currentRenderTarget = renderTarget;
30595 _currentActiveCubeFace = activeCubeFace;
30596 _currentActiveMipmapLevel = activeMipmapLevel;
30598 let useDefaultFramebuffer =
true;
30599 let framebuffer =
null;
30600 let isCube =
false;
30601 let isRenderTarget3D =
false;
30603 if ( renderTarget ) {
30605 const renderTargetProperties = properties.get( renderTarget );
30607 if ( renderTargetProperties.__useDefaultFramebuffer !==
undefined ) {
30610 state.bindFramebuffer( _gl.FRAMEBUFFER,
null );
30611 useDefaultFramebuffer =
false;
30613 }
else if ( renderTargetProperties.__webglFramebuffer ===
undefined ) {
30615 textures.setupRenderTarget( renderTarget );
30617 }
else if ( renderTargetProperties.__hasExternalTextures ) {
30620 textures.rebindTextures( renderTarget, properties.get( renderTarget.texture ).__webglTexture, properties.get( renderTarget.depthTexture ).__webglTexture );
30624 const texture = renderTarget.texture;
30626 if ( texture.isData3DTexture || texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
30628 isRenderTarget3D =
true;
30632 const __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer;
30634 if ( renderTarget.isWebGLCubeRenderTarget ) {
30636 if (
Array.isArray( __webglFramebuffer[ activeCubeFace ] ) ) {
30638 framebuffer = __webglFramebuffer[ activeCubeFace ][ activeMipmapLevel ];
30642 framebuffer = __webglFramebuffer[ activeCubeFace ];
30648 }
else if ( ( capabilities.isWebGL2 && renderTarget.samples > 0 ) && textures.useMultisampledRTT( renderTarget ) ===
false ) {
30650 framebuffer = properties.get( renderTarget ).__webglMultisampledFramebuffer;
30654 if (
Array.isArray( __webglFramebuffer ) ) {
30656 framebuffer = __webglFramebuffer[ activeMipmapLevel ];
30660 framebuffer = __webglFramebuffer;
30666 _currentViewport.copy( renderTarget.viewport );
30667 _currentScissor.copy( renderTarget.scissor );
30668 _currentScissorTest = renderTarget.scissorTest;
30672 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ).floor();
30673 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ).floor();
30674 _currentScissorTest = _scissorTest;
30678 const framebufferBound = state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30680 if ( framebufferBound && capabilities.drawBuffers && useDefaultFramebuffer ) {
30682 state.drawBuffers( renderTarget, framebuffer );
30686 state.viewport( _currentViewport );
30687 state.scissor( _currentScissor );
30688 state.setScissorTest( _currentScissorTest );
30692 const textureProperties = properties.get( renderTarget.texture );
30693 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + activeCubeFace, textureProperties.__webglTexture, activeMipmapLevel );
30695 }
else if ( isRenderTarget3D ) {
30697 const textureProperties = properties.get( renderTarget.texture );
30698 const layer = activeCubeFace || 0;
30699 _gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureProperties.__webglTexture, activeMipmapLevel || 0, layer );
30703 _currentMaterialId = - 1;
30707 this.readRenderTargetPixels =
function ( renderTarget,
x,
y, width, height, buffer, activeCubeFaceIndex ) {
30709 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) {
30711 console.error(
'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' );
30716 let framebuffer = properties.get( renderTarget ).__webglFramebuffer;
30718 if ( renderTarget.isWebGLCubeRenderTarget && activeCubeFaceIndex !==
undefined ) {
30720 framebuffer = framebuffer[ activeCubeFaceIndex ];
30724 if ( framebuffer ) {
30726 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30730 const texture = renderTarget.texture;
30731 const textureFormat = texture.format;
30732 const textureType = texture.type;
30734 if ( textureFormat !==
RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) {
30736 console.error(
'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' );
30741 const halfFloatSupportedByExt = ( textureType === HalfFloatType ) && ( extensions.has(
'EXT_color_buffer_half_float' ) || ( capabilities.isWebGL2 && extensions.has(
'EXT_color_buffer_float' ) ) );
30743 if ( textureType !==
UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) &&
30744 ! ( textureType ===
FloatType && ( capabilities.isWebGL2 || extensions.has(
'OES_texture_float' ) || extensions.has(
'WEBGL_color_buffer_float' ) ) ) &&
30745 ! halfFloatSupportedByExt ) {
30747 console.error(
'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' );
30754 if ( (
x >= 0 &&
x <= ( renderTarget.width - width ) ) && (
y >= 0 &&
y <= ( renderTarget.height - height ) ) ) {
30756 _gl.readPixels(
x,
y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer );
30764 const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer :
null;
30765 state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
30773 this.copyFramebufferToTexture =
function (
position, texture, level = 0 ) {
30775 const levelScale =
Math.pow( 2, - level );
30776 const width =
Math.floor( texture.image.width * levelScale );
30777 const height =
Math.floor( texture.image.height * levelScale );
30779 textures.setTexture2D( texture, 0 );
30781 _gl.copyTexSubImage2D( _gl.TEXTURE_2D, level, 0, 0,
position.x,
position.y, width, height );
30783 state.unbindTexture();
30787 this.copyTextureToTexture =
function (
position, srcTexture, dstTexture, level = 0 ) {
30789 const width = srcTexture.image.width;
30790 const height = srcTexture.image.height;
30791 const glFormat = utils.convert( dstTexture.format );
30792 const glType = utils.convert( dstTexture.type );
30794 textures.setTexture2D( dstTexture, 0 );
30798 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
30799 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
30800 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
30802 if ( srcTexture.isDataTexture ) {
30804 _gl.texSubImage2D( _gl.TEXTURE_2D, level,
position.x,
position.y, width, height, glFormat, glType, srcTexture.image.data );
30808 if ( srcTexture.isCompressedTexture ) {
30810 _gl.compressedTexSubImage2D( _gl.TEXTURE_2D, level,
position.x,
position.y, srcTexture.mipmaps[ 0 ].width, srcTexture.mipmaps[ 0 ].height, glFormat, srcTexture.mipmaps[ 0 ].data );
30814 _gl.texSubImage2D( _gl.TEXTURE_2D, level,
position.x,
position.y, glFormat, glType, srcTexture.image );
30821 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( _gl.TEXTURE_2D );
30823 state.unbindTexture();
30827 this.copyTextureToTexture3D =
function ( sourceBox,
position, srcTexture, dstTexture, level = 0 ) {
30829 if ( _this.isWebGL1Renderer ) {
30831 console.warn(
'THREE.WebGLRenderer.copyTextureToTexture3D: can only be used with WebGL2.' );
30836 const width = sourceBox.max.x - sourceBox.min.x + 1;
30837 const height = sourceBox.max.y - sourceBox.min.y + 1;
30838 const depth = sourceBox.max.z - sourceBox.min.z + 1;
30839 const glFormat = utils.convert( dstTexture.format );
30840 const glType = utils.convert( dstTexture.type );
30843 if ( dstTexture.isData3DTexture ) {
30845 textures.setTexture3D( dstTexture, 0 );
30846 glTarget = _gl.TEXTURE_3D;
30848 }
else if ( dstTexture.isDataArrayTexture || dstTexture.isCompressedArrayTexture ) {
30850 textures.setTexture2DArray( dstTexture, 0 );
30851 glTarget = _gl.TEXTURE_2D_ARRAY;
30855 console.warn(
'THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.' );
30860 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY );
30861 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha );
30862 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment );
30864 const unpackRowLen = _gl.getParameter( _gl.UNPACK_ROW_LENGTH );
30865 const unpackImageHeight = _gl.getParameter( _gl.UNPACK_IMAGE_HEIGHT );
30866 const unpackSkipPixels = _gl.getParameter( _gl.UNPACK_SKIP_PIXELS );
30867 const unpackSkipRows = _gl.getParameter( _gl.UNPACK_SKIP_ROWS );
30868 const unpackSkipImages = _gl.getParameter( _gl.UNPACK_SKIP_IMAGES );
30870 const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image;
30872 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, image.width );
30873 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, image.height );
30874 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, sourceBox.min.x );
30875 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, sourceBox.min.y );
30876 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, sourceBox.min.z );
30878 if ( srcTexture.isDataTexture || srcTexture.isData3DTexture ) {
30880 _gl.texSubImage3D( glTarget, level,
position.x,
position.y,
position.z, width, height, depth, glFormat, glType, image.data );
30884 if ( srcTexture.isCompressedArrayTexture ) {
30886 console.warn(
'THREE.WebGLRenderer.copyTextureToTexture3D: untested support for compressed srcTexture.' );
30887 _gl.compressedTexSubImage3D( glTarget, level,
position.x,
position.y,
position.z, width, height, depth, glFormat, image.data );
30891 _gl.texSubImage3D( glTarget, level,
position.x,
position.y,
position.z, width, height, depth, glFormat, glType, image );
30897 _gl.pixelStorei( _gl.UNPACK_ROW_LENGTH, unpackRowLen );
30898 _gl.pixelStorei( _gl.UNPACK_IMAGE_HEIGHT, unpackImageHeight );
30899 _gl.pixelStorei( _gl.UNPACK_SKIP_PIXELS, unpackSkipPixels );
30900 _gl.pixelStorei( _gl.UNPACK_SKIP_ROWS, unpackSkipRows );
30901 _gl.pixelStorei( _gl.UNPACK_SKIP_IMAGES, unpackSkipImages );
30904 if ( level === 0 && dstTexture.generateMipmaps ) _gl.generateMipmap( glTarget );
30906 state.unbindTexture();
30910 this.initTexture =
function ( texture ) {
30912 if ( texture.isCubeTexture ) {
30914 textures.setTextureCube( texture, 0 );
30916 }
else if ( texture.isData3DTexture ) {
30918 textures.setTexture3D( texture, 0 );
30920 }
else if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) {
30922 textures.setTexture2DArray( texture, 0 );
30926 textures.setTexture2D( texture, 0 );
30930 state.unbindTexture();
30934 this.resetState =
function () {
30936 _currentActiveCubeFace = 0;
30937 _currentActiveMipmapLevel = 0;
30938 _currentRenderTarget =
null;
30941 bindingStates.reset();
30945 if ( typeof __THREE_DEVTOOLS__ !==
'undefined' ) {
30947 __THREE_DEVTOOLS__.dispatchEvent(
new CustomEvent(
'observe', { detail:
this } ) );
30953 get coordinateSystem() {
30955 return WebGLCoordinateSystem;
30959 get outputColorSpace() {
30961 return this._outputColorSpace;
30965 set outputColorSpace( colorSpace ) {
30967 this._outputColorSpace = colorSpace;
30969 const gl = this.getContext();
30970 gl.drawingBufferColorSpace = colorSpace === DisplayP3ColorSpace ?
'display-p3' :
'srgb';
30971 gl.unpackColorSpace = ColorManagement.workingColorSpace === LinearDisplayP3ColorSpace ?
'display-p3' :
'srgb';
30975 get outputEncoding() {
30977 console.warn(
'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' );
30978 return this.outputColorSpace === SRGBColorSpace ? sRGBEncoding : LinearEncoding;
30982 set outputEncoding( encoding ) {
30984 console.warn(
'THREE.WebGLRenderer: Property .outputEncoding has been removed. Use .outputColorSpace instead.' );
30985 this.outputColorSpace = encoding === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace;
30989 get useLegacyLights() {
30991 console.warn(
'THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.' );
30992 return this._useLegacyLights;
30996 set useLegacyLights( value ) {
30998 console.warn(
'THREE.WebGLRenderer: The property .useLegacyLights has been deprecated. Migrate your lighting according to the following guide: https://discourse.threejs.org/t/updates-to-lighting-in-three-js-r155/53733.' );
30999 this._useLegacyLights = value;
31007 WebGL1Renderer.prototype.isWebGL1Renderer =
true;
31011 constructor( color, density = 0.00025 ) {
31013 this.isFogExp2 =
true;
31017 this.color =
new Color( color );
31018 this.density = density;
31024 return new FogExp2( this.color, this.density );
31033 color: this.color.getHex(),
31034 density: this.density
31043 constructor( color, near = 1, far = 1000 ) {
31049 this.color =
new Color( color );
31058 return new Fog( this.color, this.near, this.far );
31067 color: this.color.getHex(),
31082 this.isScene =
true;
31084 this.type =
'Scene';
31086 this.background =
null;
31087 this.environment =
null;
31090 this.backgroundBlurriness = 0;
31091 this.backgroundIntensity = 1;
31093 this.overrideMaterial =
null;
31095 if ( typeof __THREE_DEVTOOLS__ !==
'undefined' ) {
31097 __THREE_DEVTOOLS__.dispatchEvent(
new CustomEvent(
'observe', { detail:
this } ) );
31103 copy( source, recursive ) {
31105 super.copy( source, recursive );
31107 if ( source.background !==
null ) this.background = source.background.clone();
31108 if ( source.environment !==
null ) this.environment = source.environment.clone();
31109 if ( source.fog !==
null ) this.fog = source.fog.clone();
31111 this.backgroundBlurriness = source.backgroundBlurriness;
31112 this.backgroundIntensity = source.backgroundIntensity;
31114 if ( source.overrideMaterial !==
null ) this.overrideMaterial = source.overrideMaterial.clone();
31116 this.matrixAutoUpdate = source.matrixAutoUpdate;
31124 const data = super.toJSON( meta );
31126 if ( this.fog !==
null ) data.object.fog = this.fog.toJSON();
31127 if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness;
31128 if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity;
31136 class InterleavedBuffer {
31138 constructor( array, stride ) {
31140 this.isInterleavedBuffer =
true;
31142 this.array = array;
31143 this.stride = stride;
31144 this.count = array !==
undefined ? array.length / stride : 0;
31146 this.usage = StaticDrawUsage;
31147 this._updateRange = { offset: 0, count: - 1 };
31148 this.updateRanges = [];
31152 this.uuid = generateUUID();
31156 onUploadCallback() {}
31158 set needsUpdate( value ) {
31160 if ( value ===
true ) this.
version ++;
31164 get updateRange() {
31166 console.warn(
'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' );
31167 return this._updateRange;
31171 setUsage( value ) {
31173 this.usage = value;
31179 addUpdateRange( start, count ) {
31181 this.updateRanges.push( { start, count } );
31185 clearUpdateRanges() {
31187 this.updateRanges.length = 0;
31193 this.array =
new source.array.constructor( source.array );
31194 this.count = source.count;
31195 this.stride = source.stride;
31196 this.usage = source.usage;
31202 copyAt( index1, attribute, index2 ) {
31204 index1 *= this.stride;
31205 index2 *= attribute.stride;
31207 for ( let
i = 0,
l = this.stride;
i <
l;
i ++ ) {
31209 this.array[ index1 +
i ] = attribute.array[ index2 +
i ];
31217 set( value, offset = 0 ) {
31219 this.array.set( value, offset );
31227 if ( data.arrayBuffers ===
undefined ) {
31229 data.arrayBuffers = {};
31233 if ( this.array.buffer._uuid ===
undefined ) {
31235 this.array.buffer._uuid = generateUUID();
31239 if ( data.arrayBuffers[
this.array.buffer._uuid ] ===
undefined ) {
31241 data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer;
31245 const array =
new this.array.constructor( data.arrayBuffers[
this.array.buffer._uuid ] );
31247 const ib =
new this.constructor( array, this.stride );
31248 ib.setUsage( this.usage );
31254 onUpload( callback ) {
31256 this.onUploadCallback = callback;
31264 if ( data.arrayBuffers ===
undefined ) {
31266 data.arrayBuffers = {};
31272 if ( this.array.buffer._uuid ===
undefined ) {
31274 this.array.buffer._uuid = generateUUID();
31278 if ( data.arrayBuffers[
this.array.buffer._uuid ] ===
undefined ) {
31280 data.arrayBuffers[ this.array.buffer._uuid ] =
Array.from(
new Uint32Array( this.array.buffer ) );
31288 buffer: this.array.buffer._uuid,
31289 type: this.array.constructor.name,
31290 stride: this.stride
31297 const _vector$6 =
new Vector3();
31299 class InterleavedBufferAttribute {
31301 constructor( interleavedBuffer, itemSize, offset, normalized =
false ) {
31303 this.isInterleavedBufferAttribute =
true;
31307 this.data = interleavedBuffer;
31308 this.itemSize = itemSize;
31309 this.offset = offset;
31311 this.normalized = normalized;
31317 return this.data.count;
31323 return this.data.array;
31327 set needsUpdate( value ) {
31329 this.data.needsUpdate = value;
31333 applyMatrix4(
m ) {
31335 for ( let
i = 0,
l = this.data.count;
i <
l;
i ++ ) {
31337 _vector$6.fromBufferAttribute(
this,
i );
31339 _vector$6.applyMatrix4(
m );
31341 this.setXYZ(
i, _vector$6.x, _vector$6.y, _vector$6.z );
31349 applyNormalMatrix(
m ) {
31351 for ( let
i = 0,
l = this.count;
i <
l;
i ++ ) {
31353 _vector$6.fromBufferAttribute(
this,
i );
31355 _vector$6.applyNormalMatrix(
m );
31357 this.setXYZ(
i, _vector$6.x, _vector$6.y, _vector$6.z );
31365 transformDirection(
m ) {
31367 for ( let
i = 0,
l = this.count;
i <
l;
i ++ ) {
31369 _vector$6.fromBufferAttribute(
this,
i );
31371 _vector$6.transformDirection(
m );
31373 this.setXYZ(
i, _vector$6.x, _vector$6.y, _vector$6.z );
31383 if ( this.normalized )
x = normalize(
x, this.array );
31385 this.data.array[ index * this.data.stride + this.offset ] =
x;
31393 if ( this.normalized )
y = normalize(
y, this.array );
31395 this.data.array[ index * this.data.stride + this.offset + 1 ] =
y;
31403 if ( this.normalized )
z = normalize(
z, this.array );
31405 this.data.array[ index * this.data.stride + this.offset + 2 ] =
z;
31413 if ( this.normalized )
w = normalize(
w, this.array );
31415 this.data.array[ index * this.data.stride + this.offset + 3 ] =
w;
31423 let
x = this.data.array[ index * this.data.stride + this.offset ];
31425 if ( this.normalized )
x = denormalize(
x, this.array );
31433 let
y = this.data.array[ index * this.data.stride + this.offset + 1 ];
31435 if ( this.normalized )
y = denormalize(
y, this.array );
31443 let
z = this.data.array[ index * this.data.stride + this.offset + 2 ];
31445 if ( this.normalized )
z = denormalize(
z, this.array );
31453 let
w = this.data.array[ index * this.data.stride + this.offset + 3 ];
31455 if ( this.normalized )
w = denormalize(
w, this.array );
31461 setXY( index,
x,
y ) {
31463 index = index * this.data.stride + this.offset;
31465 if ( this.normalized ) {
31467 x = normalize(
x, this.array );
31468 y = normalize(
y, this.array );
31472 this.data.array[ index + 0 ] =
x;
31473 this.data.array[ index + 1 ] =
y;
31479 setXYZ( index,
x,
y,
z ) {
31481 index = index * this.data.stride + this.offset;
31483 if ( this.normalized ) {
31485 x = normalize(
x, this.array );
31486 y = normalize(
y, this.array );
31487 z = normalize(
z, this.array );
31491 this.data.array[ index + 0 ] =
x;
31492 this.data.array[ index + 1 ] =
y;
31493 this.data.array[ index + 2 ] =
z;
31499 setXYZW( index,
x,
y,
z,
w ) {
31501 index = index * this.data.stride + this.offset;
31503 if ( this.normalized ) {
31505 x = normalize(
x, this.array );
31506 y = normalize(
y, this.array );
31507 z = normalize(
z, this.array );
31508 w = normalize(
w, this.array );
31512 this.data.array[ index + 0 ] =
x;
31513 this.data.array[ index + 1 ] =
y;
31514 this.data.array[ index + 2 ] =
z;
31515 this.data.array[ index + 3 ] =
w;
31525 console.log(
'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' );
31529 for ( let
i = 0;
i < this.count;
i ++ ) {
31531 const index =
i * this.data.stride + this.offset;
31533 for ( let
j = 0;
j < this.itemSize;
j ++ ) {
31535 array.push( this.data.array[ index +
j ] );
31541 return new BufferAttribute(
new this.array.constructor( array ),
this.itemSize,
this.normalized );
31545 if ( data.interleavedBuffers ===
undefined ) {
31547 data.interleavedBuffers = {};
31551 if ( data.interleavedBuffers[
this.data.uuid ] ===
undefined ) {
31553 data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data );
31557 return new InterleavedBufferAttribute( data.interleavedBuffers[
this.data.uuid ],
this.itemSize,
this.offset,
this.normalized );
31567 console.log(
'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' );
31571 for ( let
i = 0;
i < this.count;
i ++ ) {
31573 const index =
i * this.data.stride + this.offset;
31575 for ( let
j = 0;
j < this.itemSize;
j ++ ) {
31577 array.push( this.data.array[ index +
j ] );
31586 itemSize: this.itemSize,
31587 type: this.array.constructor.name,
31589 normalized: this.normalized
31596 if ( data.interleavedBuffers ===
undefined ) {
31598 data.interleavedBuffers = {};
31602 if ( data.interleavedBuffers[
this.data.uuid ] ===
undefined ) {
31604 data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data );
31609 isInterleavedBufferAttribute:
true,
31610 itemSize: this.itemSize,
31611 data: this.data.uuid,
31612 offset: this.offset,
31613 normalized: this.normalized
31624 constructor( parameters ) {
31628 this.isSpriteMaterial =
true;
31630 this.type =
'SpriteMaterial';
31632 this.color =
new Color( 0xffffff );
31636 this.alphaMap =
null;
31640 this.sizeAttenuation =
true;
31642 this.transparent =
true;
31646 this.setValues( parameters );
31652 super.copy( source );
31654 this.color.copy( source.color );
31656 this.map = source.map;
31658 this.alphaMap = source.alphaMap;
31660 this.rotation = source.rotation;
31662 this.sizeAttenuation = source.sizeAttenuation;
31664 this.fog = source.fog;
31674 const _intersectPoint =
new Vector3();
31675 const _worldScale =
new Vector3();
31676 const _mvPosition =
new Vector3();
31678 const _alignedPosition =
new Vector2();
31679 const _rotatedPosition =
new Vector2();
31680 const _viewWorldMatrix =
new Matrix4();
31696 this.isSprite =
true;
31698 this.type =
'Sprite';
31705 - 0.5, - 0.5, 0, 0, 0,
31706 0.5, - 0.5, 0, 1, 0,
31708 - 0.5, 0.5, 0, 0, 1
31711 const interleavedBuffer =
new InterleavedBuffer( float32Array, 5 );
31713 _geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] );
31714 _geometry.setAttribute(
'position',
new InterleavedBufferAttribute( interleavedBuffer, 3, 0,
false ) );
31715 _geometry.setAttribute(
'uv',
new InterleavedBufferAttribute( interleavedBuffer, 2, 3,
false ) );
31719 this.geometry = _geometry;
31720 this.material = material;
31722 this.center =
new Vector2( 0.5, 0.5 );
31726 raycast( raycaster, intersects ) {
31728 if ( raycaster.camera ===
null ) {
31730 console.error(
'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' );
31734 _worldScale.setFromMatrixScale( this.matrixWorld );
31736 _viewWorldMatrix.copy( raycaster.camera.matrixWorld );
31737 this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse,
this.matrixWorld );
31739 _mvPosition.setFromMatrixPosition( this.modelViewMatrix );
31741 if ( raycaster.camera.isPerspectiveCamera &&
this.material.sizeAttenuation ===
false ) {
31743 _worldScale.multiplyScalar( - _mvPosition.z );
31747 const rotation = this.material.rotation;
31750 if ( rotation !== 0 ) {
31752 cos =
Math.cos( rotation );
31753 sin =
Math.sin( rotation );
31757 const center = this.center;
31759 transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31760 transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31761 transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31768 let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC,
false, _intersectPoint );
31770 if ( intersect ===
null ) {
31773 transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos );
31776 intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB,
false, _intersectPoint );
31777 if ( intersect ===
null ) {
31785 const distance = raycaster.ray.origin.distanceTo( _intersectPoint );
31787 if ( distance < raycaster.near || distance > raycaster.far )
return;
31791 distance: distance,
31792 point: _intersectPoint.clone(),
31793 uv:
Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC,
new Vector2() ),
31801 copy( source, recursive ) {
31803 super.copy( source, recursive );
31805 if ( source.center !==
undefined ) this.center.copy( source.center );
31807 this.material = source.material;
31815 function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) {
31818 _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale );
31823 _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y );
31824 _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y );
31828 _rotatedPosition.copy( _alignedPosition );
31833 vertexPosition.copy( mvPosition );
31834 vertexPosition.x += _rotatedPosition.x;
31835 vertexPosition.y += _rotatedPosition.y;
31838 vertexPosition.applyMatrix4( _viewWorldMatrix );
31851 this._currentLevel = 0;
31855 Object.defineProperties(
this, {
31865 this.autoUpdate =
true;
31871 super.copy( source,
false );
31873 const levels = source.levels;
31875 for ( let
i = 0,
l = levels.length;
i <
l;
i ++ ) {
31877 const level = levels[
i ];
31879 this.
addLevel( level.object.clone(), level.distance, level.hysteresis );
31883 this.autoUpdate = source.autoUpdate;
31889 addLevel(
object, distance = 0, hysteresis = 0 ) {
31891 distance =
Math.abs( distance );
31893 const levels = this.levels;
31897 for (
l = 0;
l < levels.length;
l ++ ) {
31899 if ( distance < levels[
l ].distance ) {
31907 levels.splice(
l, 0, { distance: distance, hysteresis: hysteresis,
object:
object } );
31909 this.
add(
object );
31915 getCurrentLevel() {
31917 return this._currentLevel;
31925 const levels = this.levels;
31927 if ( levels.length > 0 ) {
31931 for (
i = 1,
l = levels.length;
i <
l;
i ++ ) {
31933 let levelDistance = levels[
i ].distance;
31935 if ( levels[
i ].
object.visible ) {
31937 levelDistance -= levelDistance * levels[
i ].hysteresis;
31941 if ( distance < levelDistance ) {
31949 return levels[
i - 1 ].object;
31957 raycast( raycaster, intersects ) {
31959 const levels = this.levels;
31961 if ( levels.length > 0 ) {
31963 _v1$2.setFromMatrixPosition( this.matrixWorld );
31965 const distance = raycaster.ray.origin.distanceTo( _v1$2 );
31975 const levels = this.levels;
31977 if ( levels.length > 1 ) {
31979 _v1$2.setFromMatrixPosition( camera.matrixWorld );
31980 _v2$1.setFromMatrixPosition( this.matrixWorld );
31982 const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom;
31984 levels[ 0 ].object.visible =
true;
31988 for (
i = 1,
l = levels.length;
i <
l;
i ++ ) {
31990 let levelDistance = levels[
i ].distance;
31992 if ( levels[
i ].
object.visible ) {
31994 levelDistance -= levelDistance * levels[
i ].hysteresis;
31998 if ( distance >= levelDistance ) {
32000 levels[
i - 1 ].object.visible =
false;
32001 levels[
i ].object.visible =
true;
32011 this._currentLevel =
i - 1;
32013 for ( ;
i <
l;
i ++ ) {
32015 levels[
i ].object.visible =
false;
32025 const data = super.toJSON( meta );
32027 if ( this.autoUpdate ===
false ) data.object.autoUpdate =
false;
32029 data.object.levels = [];
32031 const levels = this.levels;
32033 for ( let
i = 0,
l = levels.length;
i <
l;
i ++ ) {
32035 const level = levels[
i ];
32037 data.object.levels.push( {
32038 object: level.object.uuid,
32039 distance: level.distance,
32040 hysteresis: level.hysteresis
32051 const _basePosition =
new Vector3();
32053 const _skinIndex =
new Vector4();
32054 const _skinWeight =
new Vector4();
32056 const _vector3 =
new Vector3();
32057 const _matrix4 =
new Matrix4();
32058 const _vertex =
new Vector3();
32060 const _sphere$4 =
new Sphere();
32061 const _inverseMatrix$2 =
new Matrix4();
32062 const _ray$2 =
new Ray();
32066 constructor( geometry, material ) {
32068 super( geometry, material );
32070 this.isSkinnedMesh =
true;
32072 this.type =
'SkinnedMesh';
32074 this.bindMode = AttachedBindMode;
32075 this.bindMatrix =
new Matrix4();
32076 this.bindMatrixInverse =
new Matrix4();
32078 this.boundingBox =
null;
32079 this.boundingSphere =
null;
32083 computeBoundingBox() {
32085 const geometry = this.geometry;
32087 if ( this.boundingBox ===
null ) {
32089 this.boundingBox =
new Box3();
32093 this.boundingBox.makeEmpty();
32095 const positionAttribute = geometry.getAttribute(
'position' );
32097 for ( let
i = 0;
i < positionAttribute.count;
i ++ ) {
32099 this.getVertexPosition(
i, _vertex );
32100 this.boundingBox.expandByPoint( _vertex );
32106 computeBoundingSphere() {
32108 const geometry = this.geometry;
32110 if ( this.boundingSphere ===
null ) {
32112 this.boundingSphere =
new Sphere();
32116 this.boundingSphere.makeEmpty();
32118 const positionAttribute = geometry.getAttribute(
'position' );
32120 for ( let
i = 0;
i < positionAttribute.count;
i ++ ) {
32122 this.getVertexPosition(
i, _vertex );
32123 this.boundingSphere.expandByPoint( _vertex );
32129 copy( source, recursive ) {
32131 super.copy( source, recursive );
32133 this.bindMode = source.bindMode;
32134 this.bindMatrix.copy( source.bindMatrix );
32135 this.bindMatrixInverse.copy( source.bindMatrixInverse );
32137 this.skeleton = source.skeleton;
32139 if ( source.boundingBox !==
null ) this.boundingBox = source.boundingBox.clone();
32140 if ( source.boundingSphere !==
null ) this.boundingSphere = source.boundingSphere.clone();
32146 raycast( raycaster, intersects ) {
32148 const material = this.material;
32149 const matrixWorld = this.matrixWorld;
32155 if ( this.boundingSphere ===
null ) this.computeBoundingSphere();
32157 _sphere$4.copy( this.boundingSphere );
32158 _sphere$4.applyMatrix4( matrixWorld );
32160 if ( raycaster.ray.intersectsSphere( _sphere$4 ) ===
false )
return;
32164 _inverseMatrix$2.copy( matrixWorld ).invert();
32165 _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 );
32169 if ( this.boundingBox !==
null ) {
32171 if ( _ray$2.intersectsBox(
this.boundingBox ) ===
false )
return;
32177 this._computeIntersections( raycaster, intersects, _ray$2 );
32181 getVertexPosition( index, target ) {
32183 super.getVertexPosition( index, target );
32185 this.applyBoneTransform( index, target );
32191 bind( skeleton, bindMatrix ) {
32193 this.skeleton = skeleton;
32199 this.skeleton.calculateInverses();
32201 bindMatrix = this.matrixWorld;
32205 this.bindMatrix.copy( bindMatrix );
32206 this.bindMatrixInverse.copy( bindMatrix ).invert();
32212 this.skeleton.pose();
32218 const vector =
new Vector4();
32220 const skinWeight = this.geometry.attributes.skinWeight;
32222 for ( let
i = 0,
l = skinWeight.count;
i <
l;
i ++ ) {
32224 vector.fromBufferAttribute( skinWeight,
i );
32226 const scale = 1.0 / vector.manhattanLength();
32228 if ( scale !== Infinity ) {
32230 vector.multiplyScalar( scale );
32234 vector.set( 1, 0, 0, 0 );
32238 skinWeight.setXYZW(
i, vector.x, vector.y, vector.z, vector.w );
32246 super.updateMatrixWorld( force );
32248 if ( this.bindMode === AttachedBindMode ) {
32250 this.bindMatrixInverse.copy( this.matrixWorld ).invert();
32252 }
else if ( this.bindMode === DetachedBindMode ) {
32254 this.bindMatrixInverse.copy( this.bindMatrix ).invert();
32258 console.warn(
'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode );
32264 applyBoneTransform( index, vector ) {
32266 const skeleton = this.skeleton;
32267 const geometry = this.geometry;
32269 _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index );
32270 _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index );
32272 _basePosition.copy( vector ).applyMatrix4( this.bindMatrix );
32274 vector.set( 0, 0, 0 );
32276 for ( let
i = 0;
i < 4;
i ++ ) {
32278 const weight = _skinWeight.getComponent(
i );
32280 if ( weight !== 0 ) {
32282 const boneIndex = _skinIndex.getComponent(
i );
32284 _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] );
32286 vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight );
32292 return vector.applyMatrix4( this.bindMatrixInverse );
32296 boneTransform( index, vector ) {
32298 console.warn(
'THREE.SkinnedMesh: .boneTransform() was renamed to .applyBoneTransform() in r151.' );
32299 return this.applyBoneTransform( index, vector );
32312 this.isBone =
true;
32314 this.type =
'Bone';
32322 constructor( data =
null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter =
NearestFilter, minFilter =
NearestFilter, anisotropy, colorSpace ) {
32324 super(
null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
32326 this.isDataTexture =
true;
32328 this.image = { data: data, width: width, height: height };
32330 this.generateMipmaps =
false;
32331 this.flipY =
false;
32332 this.unpackAlignment = 1;
32338 const _offsetMatrix =
new Matrix4();
32339 const _identityMatrix$1 =
new Matrix4();
32343 constructor( bones = [], boneInverses = [] ) {
32345 this.uuid = generateUUID();
32347 this.bones = bones.slice( 0 );
32348 this.boneInverses = boneInverses;
32349 this.boneMatrices =
null;
32351 this.boneTexture =
null;
32359 const bones = this.bones;
32360 const boneInverses = this.boneInverses;
32362 this.boneMatrices =
new Float32Array( bones.length * 16 );
32366 if ( boneInverses.length === 0 ) {
32374 if ( bones.length !== boneInverses.length ) {
32376 console.warn(
'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' );
32378 this.boneInverses = [];
32380 for ( let
i = 0, il = this.bones.length;
i < il;
i ++ ) {
32382 this.boneInverses.push(
new Matrix4() );
32394 this.boneInverses.length = 0;
32396 for ( let
i = 0, il = this.bones.length;
i < il;
i ++ ) {
32398 const inverse =
new Matrix4();
32400 if ( this.bones[
i ] ) {
32402 inverse.copy( this.bones[
i ].matrixWorld ).invert();
32406 this.boneInverses.push( inverse );
32416 for ( let
i = 0, il = this.bones.length;
i < il;
i ++ ) {
32418 const bone = this.bones[
i ];
32422 bone.matrixWorld.copy( this.boneInverses[
i ] ).invert();
32430 for ( let
i = 0, il = this.bones.length;
i < il;
i ++ ) {
32432 const bone = this.bones[
i ];
32436 if ( bone.parent && bone.parent.isBone ) {
32438 bone.matrix.copy( bone.parent.matrixWorld ).invert();
32439 bone.matrix.multiply( bone.matrixWorld );
32443 bone.matrix.copy( bone.matrixWorld );
32447 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale );
32457 const bones = this.bones;
32458 const boneInverses = this.boneInverses;
32459 const boneMatrices = this.boneMatrices;
32460 const boneTexture = this.boneTexture;
32464 for ( let
i = 0, il = bones.length;
i < il;
i ++ ) {
32468 const matrix = bones[
i ] ? bones[
i ].matrixWorld : _identityMatrix$1;
32470 _offsetMatrix.multiplyMatrices( matrix, boneInverses[
i ] );
32471 _offsetMatrix.toArray( boneMatrices,
i * 16 );
32475 if ( boneTexture !==
null ) {
32477 boneTexture.needsUpdate =
true;
32485 return new Skeleton( this.bones, this.boneInverses );
32489 computeBoneTexture() {
32498 let size =
Math.sqrt( this.bones.length * 4 );
32499 size =
Math.ceil( size / 4 ) * 4;
32500 size =
Math.max( size, 4 );
32502 const boneMatrices =
new Float32Array( size * size * 4 );
32503 boneMatrices.set( this.boneMatrices );
32506 boneTexture.needsUpdate =
true;
32508 this.boneMatrices = boneMatrices;
32509 this.boneTexture = boneTexture;
32515 getBoneByName( name ) {
32517 for ( let
i = 0, il = this.bones.length;
i < il;
i ++ ) {
32519 const bone = this.bones[
i ];
32521 if ( bone.name === name ) {
32535 if ( this.boneTexture !==
null ) {
32537 this.boneTexture.dispose();
32539 this.boneTexture =
null;
32545 fromJSON( json, bones ) {
32547 this.uuid = json.uuid;
32549 for ( let
i = 0,
l = json.bones.length;
i <
l;
i ++ ) {
32551 const uuid = json.bones[
i ];
32552 let bone = bones[ uuid ];
32556 console.warn(
'THREE.Skeleton: No bone found with UUID:', uuid );
32561 this.bones.push( bone );
32578 generator:
'Skeleton.toJSON'
32584 data.uuid = this.uuid;
32586 const bones = this.bones;
32587 const boneInverses = this.boneInverses;
32589 for ( let
i = 0,
l = bones.length;
i <
l;
i ++ ) {
32591 const bone = bones[
i ];
32592 data.bones.push( bone.uuid );
32594 const boneInverse = boneInverses[
i ];
32595 data.boneInverses.push( boneInverse.toArray() );
32607 constructor( array, itemSize, normalized, meshPerAttribute = 1 ) {
32609 super( array, itemSize, normalized );
32611 this.isInstancedBufferAttribute =
true;
32613 this.meshPerAttribute = meshPerAttribute;
32619 super.copy( source );
32621 this.meshPerAttribute = source.meshPerAttribute;
32629 const data = super.toJSON();
32631 data.meshPerAttribute = this.meshPerAttribute;
32633 data.isInstancedBufferAttribute =
true;
32641 const _instanceLocalMatrix =
new Matrix4();
32642 const _instanceWorldMatrix =
new Matrix4();
32644 const _instanceIntersects = [];
32646 const _box3 =
new Box3();
32647 const _identity =
new Matrix4();
32648 const _mesh$1 =
new Mesh();
32649 const _sphere$3 =
new Sphere();
32651 class InstancedMesh
extends Mesh {
32653 constructor( geometry, material, count ) {
32655 super( geometry, material );
32657 this.isInstancedMesh =
true;
32659 this.instanceMatrix =
new InstancedBufferAttribute(
new Float32Array( count * 16 ), 16 );
32660 this.instanceColor =
null;
32662 this.count = count;
32664 this.boundingBox =
null;
32665 this.boundingSphere =
null;
32667 for ( let
i = 0;
i < count;
i ++ ) {
32669 this.setMatrixAt(
i, _identity );
32675 computeBoundingBox() {
32677 const geometry = this.geometry;
32678 const count = this.count;
32680 if ( this.boundingBox ===
null ) {
32682 this.boundingBox =
new Box3();
32686 if ( geometry.boundingBox ===
null ) {
32688 geometry.computeBoundingBox();
32692 this.boundingBox.makeEmpty();
32694 for ( let
i = 0;
i < count;
i ++ ) {
32696 this.getMatrixAt(
i, _instanceLocalMatrix );
32698 _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix );
32700 this.boundingBox.union( _box3 );
32706 computeBoundingSphere() {
32708 const geometry = this.geometry;
32709 const count = this.count;
32711 if ( this.boundingSphere ===
null ) {
32713 this.boundingSphere =
new Sphere();
32717 if ( geometry.boundingSphere ===
null ) {
32719 geometry.computeBoundingSphere();
32723 this.boundingSphere.makeEmpty();
32725 for ( let
i = 0;
i < count;
i ++ ) {
32727 this.getMatrixAt(
i, _instanceLocalMatrix );
32729 _sphere$3.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix );
32731 this.boundingSphere.union( _sphere$3 );
32737 copy( source, recursive ) {
32739 super.copy( source, recursive );
32741 this.instanceMatrix.copy( source.instanceMatrix );
32743 if ( source.instanceColor !==
null ) this.instanceColor = source.instanceColor.clone();
32745 this.count = source.count;
32747 if ( source.boundingBox !==
null ) this.boundingBox = source.boundingBox.clone();
32748 if ( source.boundingSphere !==
null ) this.boundingSphere = source.boundingSphere.clone();
32754 getColorAt( index, color ) {
32756 color.fromArray( this.instanceColor.array, index * 3 );
32760 getMatrixAt( index, matrix ) {
32762 matrix.fromArray( this.instanceMatrix.array, index * 16 );
32766 raycast( raycaster, intersects ) {
32768 const matrixWorld = this.matrixWorld;
32769 const raycastTimes = this.count;
32771 _mesh$1.geometry = this.geometry;
32772 _mesh$1.material = this.material;
32774 if ( _mesh$1.material ===
undefined )
return;
32778 if ( this.boundingSphere ===
null ) this.computeBoundingSphere();
32780 _sphere$3.copy( this.boundingSphere );
32781 _sphere$3.applyMatrix4( matrixWorld );
32783 if ( raycaster.ray.intersectsSphere( _sphere$3 ) ===
false )
return;
32787 for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) {
32791 this.getMatrixAt( instanceId, _instanceLocalMatrix );
32793 _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix );
32797 _mesh$1.matrixWorld = _instanceWorldMatrix;
32799 _mesh$1.raycast( raycaster, _instanceIntersects );
32803 for ( let
i = 0,
l = _instanceIntersects.length;
i <
l;
i ++ ) {
32805 const intersect = _instanceIntersects[
i ];
32806 intersect.instanceId = instanceId;
32807 intersect.object =
this;
32808 intersects.push( intersect );
32812 _instanceIntersects.length = 0;
32818 setColorAt( index, color ) {
32820 if ( this.instanceColor ===
null ) {
32822 this.instanceColor =
new InstancedBufferAttribute(
new Float32Array( this.instanceMatrix.count * 3 ), 3 );
32826 color.toArray( this.instanceColor.array, index * 3 );
32830 setMatrixAt( index, matrix ) {
32832 matrix.toArray( this.instanceMatrix.array, index * 16 );
32842 this.dispatchEvent( { type:
'dispose' } );
32848 function sortOpaque(
a,
b ) {
32854 function sortTransparent(
a,
b ) {
32860 class MultiDrawRenderList {
32870 push( drawRange,
z ) {
32872 const pool = this.pool;
32873 const list = this.list;
32874 if ( this.index >= pool.length ) {
32886 const item = pool[ this.index ];
32890 item.start = drawRange.start;
32891 item.count = drawRange.count;
32898 this.list.length = 0;
32905 const ID_ATTR_NAME =
'batchId';
32906 const _matrix =
new Matrix4();
32907 const _invMatrixWorld =
new Matrix4();
32908 const _identityMatrix =
new Matrix4();
32909 const _projScreenMatrix$2 =
new Matrix4();
32910 const _frustum =
new Frustum();
32911 const _box$1 =
new Box3();
32912 const _sphere$2 =
new Sphere();
32913 const _vector$5 =
new Vector3();
32914 const _renderList =
new MultiDrawRenderList();
32915 const _mesh =
new Mesh();
32916 const _batchIntersects = [];
32926 function copyAttributeData( src, target, targetOffset = 0 ) {
32928 const itemSize = target.itemSize;
32929 if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) {
32933 const vertexCount = src.count;
32934 for ( let
i = 0;
i < vertexCount;
i ++ ) {
32936 for ( let
c = 0;
c < itemSize;
c ++ ) {
32938 target.setComponent(
i + targetOffset,
c, src.getComponent(
i,
c ) );
32947 target.array.set( src.array, targetOffset * itemSize );
32951 target.needsUpdate =
true;
32955 class BatchedMesh
extends Mesh {
32957 get maxGeometryCount() {
32959 return this._maxGeometryCount;
32963 constructor( maxGeometryCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) {
32967 this.isBatchedMesh =
true;
32968 this.perObjectFrustumCulled =
true;
32969 this.sortObjects =
true;
32970 this.boundingBox =
null;
32971 this.boundingSphere =
null;
32972 this.customSort =
null;
32974 this._drawRanges = [];
32975 this._reservedRanges = [];
32977 this._visibility = [];
32981 this._maxGeometryCount = maxGeometryCount;
32982 this._maxVertexCount = maxVertexCount;
32983 this._maxIndexCount = maxIndexCount;
32985 this._geometryInitialized =
false;
32986 this._geometryCount = 0;
32987 this._multiDrawCounts =
new Int32Array( maxGeometryCount );
32988 this._multiDrawStarts =
new Int32Array( maxGeometryCount );
32989 this._multiDrawCount = 0;
32990 this._visibilityChanged =
true;
32993 this._matricesTexture =
null;
32995 this._initMatricesTexture();
32999 _initMatricesTexture() {
33008 let size =
Math.sqrt( this._maxGeometryCount * 4 );
33009 size =
Math.ceil( size / 4 ) * 4;
33010 size =
Math.max( size, 4 );
33012 const matricesArray =
new Float32Array( size * size * 4 );
33015 this._matricesTexture = matricesTexture;
33019 _initializeGeometry( reference ) {
33021 const geometry = this.geometry;
33022 const maxVertexCount = this._maxVertexCount;
33023 const maxGeometryCount = this._maxGeometryCount;
33024 const maxIndexCount = this._maxIndexCount;
33025 if ( this._geometryInitialized ===
false ) {
33027 for (
const attributeName in reference.attributes ) {
33029 const srcAttribute = reference.getAttribute( attributeName );
33030 const { array, itemSize, normalized } = srcAttribute;
33032 const dstArray =
new array.constructor( maxVertexCount * itemSize );
33033 const dstAttribute =
new srcAttribute.constructor( dstArray, itemSize, normalized );
33034 dstAttribute.setUsage( srcAttribute.usage );
33036 geometry.setAttribute( attributeName, dstAttribute );
33040 if ( reference.getIndex() !==
null ) {
33042 const indexArray = maxVertexCount > 65536
33050 const idArray = maxGeometryCount > 65536
33053 geometry.setAttribute( ID_ATTR_NAME,
new BufferAttribute( idArray, 1 ) );
33055 this._geometryInitialized =
true;
33062 _validateGeometry( geometry ) {
33065 if ( geometry.getAttribute( ID_ATTR_NAME ) ) {
33067 throw new Error( `BatchedMesh:
Geometry cannot use attribute
"${ ID_ATTR_NAME }"` );
33072 const batchGeometry = this.geometry;
33073 if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) {
33075 throw new Error(
'BatchedMesh: All geometries must consistently have "index".' );
33079 for (
const attributeName in batchGeometry.attributes ) {
33081 if ( attributeName === ID_ATTR_NAME ) {
33087 if ( ! geometry.hasAttribute( attributeName ) ) {
33089 throw new Error( `BatchedMesh: Added geometry missing
"${ attributeName }". All geometries must have consistent attributes.` );
33093 const srcAttribute = geometry.getAttribute( attributeName );
33094 const dstAttribute = batchGeometry.getAttribute( attributeName );
33095 if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) {
33097 throw new Error(
'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' );
33105 setCustomSort( func ) {
33107 this.customSort = func;
33112 computeBoundingBox() {
33114 if ( this.boundingBox ===
null ) {
33116 this.boundingBox =
new Box3();
33120 const geometryCount = this._geometryCount;
33121 const boundingBox = this.boundingBox;
33122 const active = this._active;
33124 boundingBox.makeEmpty();
33125 for ( let
i = 0;
i < geometryCount;
i ++ ) {
33127 if ( active[
i ] ===
false )
continue;
33129 this.getMatrixAt(
i, _matrix );
33130 this.getBoundingBoxAt(
i, _box$1 ).applyMatrix4( _matrix );
33131 boundingBox.union( _box$1 );
33137 computeBoundingSphere() {
33139 if ( this.boundingSphere ===
null ) {
33141 this.boundingSphere =
new Sphere();
33145 const geometryCount = this._geometryCount;
33146 const boundingSphere = this.boundingSphere;
33147 const active = this._active;
33149 boundingSphere.makeEmpty();
33150 for ( let
i = 0;
i < geometryCount;
i ++ ) {
33152 if ( active[
i ] ===
false )
continue;
33154 this.getMatrixAt(
i, _matrix );
33155 this.getBoundingSphereAt(
i, _sphere$2 ).applyMatrix4( _matrix );
33156 boundingSphere.union( _sphere$2 );
33162 addGeometry( geometry, vertexCount = - 1, indexCount = - 1 ) {
33164 this._initializeGeometry( geometry );
33166 this._validateGeometry( geometry );
33169 if ( this._geometryCount >= this._maxGeometryCount ) {
33171 throw new Error(
'BatchedMesh: Maximum geometry count reached.' );
33176 const reservedRange = {
33183 let lastRange =
null;
33184 const reservedRanges = this._reservedRanges;
33185 const drawRanges = this._drawRanges;
33186 const bounds = this._bounds;
33187 if ( this._geometryCount !== 0 ) {
33189 lastRange = reservedRanges[ reservedRanges.length - 1 ];
33193 if ( vertexCount === - 1 ) {
33195 reservedRange.vertexCount = geometry.getAttribute(
'position' ).count;
33199 reservedRange.vertexCount = vertexCount;
33203 if ( lastRange ===
null ) {
33205 reservedRange.vertexStart = 0;
33209 reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount;
33213 const index = geometry.getIndex();
33214 const hasIndex = index !==
null;
33217 if ( indexCount === - 1 ) {
33219 reservedRange.indexCount = index.count;
33223 reservedRange.indexCount = indexCount;
33227 if ( lastRange ===
null ) {
33229 reservedRange.indexStart = 0;
33233 reservedRange.indexStart = lastRange.indexStart + lastRange.indexCount;
33240 reservedRange.indexStart !== - 1 &&
33241 reservedRange.indexStart + reservedRange.indexCount >
this._maxIndexCount ||
33242 reservedRange.vertexStart + reservedRange.vertexCount >
this._maxVertexCount
33245 throw new Error(
'BatchedMesh: Reserved space request exceeds the maximum buffer size.' );
33249 const visibility = this._visibility;
33250 const active = this._active;
33251 const matricesTexture = this._matricesTexture;
33252 const matricesArray = this._matricesTexture.image.data;
33255 visibility.push(
true );
33256 active.push(
true );
33259 const geometryId = this._geometryCount;
33260 this._geometryCount ++;
33263 _identityMatrix.toArray( matricesArray, geometryId * 16 );
33264 matricesTexture.needsUpdate =
true;
33267 reservedRanges.push( reservedRange );
33269 start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart,
33273 boxInitialized:
false,
33276 sphereInitialized:
false,
33281 const idAttribute = this.geometry.getAttribute( ID_ATTR_NAME );
33282 for ( let
i = 0;
i < reservedRange.vertexCount;
i ++ ) {
33284 idAttribute.setX( reservedRange.vertexStart +
i, geometryId );
33288 idAttribute.needsUpdate =
true;
33291 this.setGeometryAt( geometryId, geometry );
33297 setGeometryAt(
id, geometry ) {
33299 if (
id >= this._geometryCount ) {
33301 throw new Error(
'BatchedMesh: Maximum geometry count reached.' );
33305 this._validateGeometry( geometry );
33307 const batchGeometry = this.geometry;
33308 const hasIndex = batchGeometry.getIndex() !==
null;
33309 const dstIndex = batchGeometry.getIndex();
33310 const srcIndex = geometry.getIndex();
33311 const reservedRange = this._reservedRanges[ id ];
33314 srcIndex.count > reservedRange.indexCount ||
33315 geometry.attributes.position.count > reservedRange.vertexCount
33318 throw new Error(
'BatchedMesh: Reserved space not large enough for provided geometry.' );
33323 const vertexStart = reservedRange.vertexStart;
33324 const vertexCount = reservedRange.vertexCount;
33325 for (
const attributeName in batchGeometry.attributes ) {
33327 if ( attributeName === ID_ATTR_NAME ) {
33334 const srcAttribute = geometry.getAttribute( attributeName );
33335 const dstAttribute = batchGeometry.getAttribute( attributeName );
33336 copyAttributeData( srcAttribute, dstAttribute, vertexStart );
33339 const itemSize = srcAttribute.itemSize;
33340 for ( let
i = srcAttribute.count,
l = vertexCount;
i <
l;
i ++ ) {
33342 const index = vertexStart +
i;
33343 for ( let
c = 0;
c < itemSize;
c ++ ) {
33345 dstAttribute.setComponent( index,
c, 0 );
33351 dstAttribute.needsUpdate =
true;
33358 const indexStart = reservedRange.indexStart;
33361 for ( let
i = 0;
i < srcIndex.count;
i ++ ) {
33363 dstIndex.setX( indexStart +
i, vertexStart + srcIndex.getX(
i ) );
33368 for ( let
i = srcIndex.count,
l = reservedRange.indexCount;
i <
l;
i ++ ) {
33370 dstIndex.setX( indexStart +
i, vertexStart );
33374 dstIndex.needsUpdate =
true;
33379 const bound = this._bounds[ id ];
33380 if ( geometry.boundingBox !==
null ) {
33382 bound.box.copy( geometry.boundingBox );
33383 bound.boxInitialized =
true;
33387 bound.boxInitialized =
false;
33391 if ( geometry.boundingSphere !==
null ) {
33393 bound.sphere.copy( geometry.boundingSphere );
33394 bound.sphereInitialized =
true;
33398 bound.sphereInitialized =
false;
33403 const drawRange = this._drawRanges[ id ];
33404 const posAttr = geometry.getAttribute(
'position' );
33405 drawRange.count = hasIndex ? srcIndex.count : posAttr.count;
33406 this._visibilityChanged =
true;
33412 deleteGeometry( geometryId ) {
33416 const active = this._active;
33417 if ( geometryId >= active.length || active[ geometryId ] ===
false ) {
33423 active[ geometryId ] =
false;
33424 this._visibilityChanged =
true;
33431 getBoundingBoxAt(
id, target ) {
33433 const active = this._active;
33434 if ( active[
id ] ===
false ) {
33441 const bound = this._bounds[ id ];
33442 const box = bound.box;
33443 const geometry = this.geometry;
33444 if ( bound.boxInitialized ===
false ) {
33448 const index = geometry.index;
33449 const position = geometry.attributes.position;
33450 const drawRange = this._drawRanges[ id ];
33451 for ( let
i = drawRange.start,
l = drawRange.start + drawRange.count;
i <
l;
i ++ ) {
33456 iv = index.getX( iv );
33460 box.expandByPoint( _vector$5.fromBufferAttribute(
position, iv ) );
33464 bound.boxInitialized =
true;
33468 target.copy( box );
33474 getBoundingSphereAt(
id, target ) {
33476 const active = this._active;
33477 if ( active[
id ] ===
false ) {
33484 const bound = this._bounds[ id ];
33485 const sphere = bound.sphere;
33486 const geometry = this.geometry;
33487 if ( bound.sphereInitialized ===
false ) {
33489 sphere.makeEmpty();
33491 this.getBoundingBoxAt(
id, _box$1 );
33492 _box$1.getCenter( sphere.center );
33494 const index = geometry.index;
33495 const position = geometry.attributes.position;
33496 const drawRange = this._drawRanges[ id ];
33498 let maxRadiusSq = 0;
33499 for ( let
i = drawRange.start,
l = drawRange.start + drawRange.count;
i <
l;
i ++ ) {
33504 iv = index.getX( iv );
33508 _vector$5.fromBufferAttribute(
position, iv );
33509 maxRadiusSq =
Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) );
33513 sphere.radius =
Math.sqrt( maxRadiusSq );
33514 bound.sphereInitialized =
true;
33518 target.copy( sphere );
33523 setMatrixAt( geometryId, matrix ) {
33528 const active = this._active;
33529 const matricesTexture = this._matricesTexture;
33530 const matricesArray = this._matricesTexture.image.data;
33531 const geometryCount = this._geometryCount;
33532 if ( geometryId >= geometryCount || active[ geometryId ] ===
false ) {
33538 matrix.toArray( matricesArray, geometryId * 16 );
33539 matricesTexture.needsUpdate =
true;
33545 getMatrixAt( geometryId, matrix ) {
33547 const active = this._active;
33548 const matricesArray = this._matricesTexture.image.data;
33549 const geometryCount = this._geometryCount;
33550 if ( geometryId >= geometryCount || active[ geometryId ] ===
false ) {
33556 return matrix.fromArray( matricesArray, geometryId * 16 );
33560 setVisibleAt( geometryId, value ) {
33562 const visibility = this._visibility;
33563 const active = this._active;
33564 const geometryCount = this._geometryCount;
33569 geometryId >= geometryCount ||
33570 active[ geometryId ] ===
false ||
33571 visibility[ geometryId ] === value
33578 visibility[ geometryId ] = value;
33579 this._visibilityChanged =
true;
33585 getVisibleAt( geometryId ) {
33587 const visibility = this._visibility;
33588 const active = this._active;
33589 const geometryCount = this._geometryCount;
33592 if ( geometryId >= geometryCount || active[ geometryId ] ===
false ) {
33598 return visibility[ geometryId ];
33602 raycast( raycaster, intersects ) {
33604 const visibility = this._visibility;
33605 const active = this._active;
33606 const drawRanges = this._drawRanges;
33607 const geometryCount = this._geometryCount;
33608 const matrixWorld = this.matrixWorld;
33609 const batchGeometry = this.geometry;
33612 _mesh.material = this.material;
33613 _mesh.geometry.index = batchGeometry.index;
33614 _mesh.geometry.attributes = batchGeometry.attributes;
33615 if ( _mesh.geometry.boundingBox ===
null ) {
33617 _mesh.geometry.boundingBox =
new Box3();
33621 if ( _mesh.geometry.boundingSphere ===
null ) {
33623 _mesh.geometry.boundingSphere =
new Sphere();
33627 for ( let
i = 0;
i < geometryCount;
i ++ ) {
33629 if ( ! visibility[
i ] || ! active[
i ] ) {
33635 const drawRange = drawRanges[
i ];
33636 _mesh.geometry.setDrawRange( drawRange.start, drawRange.count );
33639 this.getMatrixAt(
i, _mesh.matrixWorld ).premultiply( matrixWorld );
33640 this.getBoundingBoxAt(
i, _mesh.geometry.boundingBox );
33641 this.getBoundingSphereAt(
i, _mesh.geometry.boundingSphere );
33642 _mesh.raycast( raycaster, _batchIntersects );
33645 for ( let
j = 0,
l = _batchIntersects.length;
j <
l;
j ++ ) {
33647 const intersect = _batchIntersects[
j ];
33648 intersect.object =
this;
33649 intersect.batchId =
i;
33650 intersects.push( intersect );
33654 _batchIntersects.length = 0;
33658 _mesh.material =
null;
33659 _mesh.geometry.index =
null;
33660 _mesh.geometry.attributes = {};
33661 _mesh.geometry.setDrawRange( 0, Infinity );
33667 super.copy( source );
33669 this.geometry = source.geometry.clone();
33670 this.perObjectFrustumCulled = source.perObjectFrustumCulled;
33671 this.sortObjects = source.sortObjects;
33672 this.boundingBox = source.boundingBox !==
null ? source.boundingBox.clone() :
null;
33673 this.boundingSphere = source.boundingSphere !==
null ? source.boundingSphere.clone() :
null;
33675 this._drawRanges = source._drawRanges.map( range => ( { ...range } ) );
33676 this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) );
33678 this._visibility = source._visibility.slice();
33679 this._active = source._active.slice();
33680 this._bounds = source._bounds.map( bound => ( {
33681 boxInitialized: bound.boxInitialized,
33682 box: bound.box.clone(),
33684 sphereInitialized: bound.sphereInitialized,
33685 sphere: bound.sphere.clone()
33688 this._maxGeometryCount = source._maxGeometryCount;
33689 this._maxVertexCount = source._maxVertexCount;
33690 this._maxIndexCount = source._maxIndexCount;
33692 this._geometryInitialized = source._geometryInitialized;
33693 this._geometryCount = source._geometryCount;
33694 this._multiDrawCounts = source._multiDrawCounts.slice();
33695 this._multiDrawStarts = source._multiDrawStarts.slice();
33697 this._matricesTexture = source._matricesTexture.clone();
33698 this._matricesTexture.image.data = this._matricesTexture.image.slice();
33707 this.geometry.dispose();
33709 this._matricesTexture.dispose();
33710 this._matricesTexture =
null;
33715 onBeforeRender( renderer, scene, camera, geometry, material ) {
33719 if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) {
33727 const index = geometry.getIndex();
33728 const bytesPerElement = index ===
null ? 1 : index.array.BYTES_PER_ELEMENT;
33730 const visibility = this._visibility;
33731 const multiDrawStarts = this._multiDrawStarts;
33732 const multiDrawCounts = this._multiDrawCounts;
33733 const drawRanges = this._drawRanges;
33734 const perObjectFrustumCulled = this.perObjectFrustumCulled;
33737 if ( perObjectFrustumCulled ) {
33739 _projScreenMatrix$2
33740 .multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse )
33741 .multiply( this.matrixWorld );
33742 _frustum.setFromProjectionMatrix(
33743 _projScreenMatrix$2,
33744 renderer.isWebGPURenderer ? WebGPUCoordinateSystem : WebGLCoordinateSystem
33750 if ( this.sortObjects ) {
33753 _invMatrixWorld.copy( this.matrixWorld ).invert();
33754 _vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _invMatrixWorld );
33756 for ( let
i = 0,
l = visibility.length;
i <
l;
i ++ ) {
33758 if ( visibility[
i ] ) {
33761 this.getMatrixAt(
i, _matrix );
33762 this.getBoundingSphereAt(
i, _sphere$2 ).applyMatrix4( _matrix );
33765 let culled =
false;
33766 if ( perObjectFrustumCulled ) {
33768 culled = ! _frustum.intersectsSphere( _sphere$2 );
33775 const z = _vector$5.distanceTo( _sphere$2.center );
33776 _renderList.push( drawRanges[
i ],
z );
33785 const list = _renderList.list;
33786 const customSort = this.customSort;
33787 if ( customSort ===
null ) {
33789 list.sort( material.transparent ? sortTransparent : sortOpaque );
33793 customSort.call(
this, list, camera );
33797 for ( let
i = 0,
l = list.length;
i <
l;
i ++ ) {
33799 const item = list[
i ];
33800 multiDrawStarts[ count ] = item.start * bytesPerElement;
33801 multiDrawCounts[ count ] = item.count;
33806 _renderList.reset();
33810 for ( let
i = 0,
l = visibility.length;
i <
l;
i ++ ) {
33812 if ( visibility[
i ] ) {
33815 let culled =
false;
33816 if ( perObjectFrustumCulled ) {
33819 this.getMatrixAt(
i, _matrix );
33820 this.getBoundingSphereAt(
i, _sphere$2 ).applyMatrix4( _matrix );
33821 culled = ! _frustum.intersectsSphere( _sphere$2 );
33827 const range = drawRanges[
i ];
33828 multiDrawStarts[ count ] = range.start * bytesPerElement;
33829 multiDrawCounts[ count ] = range.count;
33840 this._multiDrawCount = count;
33841 this._visibilityChanged =
false;
33845 onBeforeShadow( renderer,
object, camera, shadowCamera, geometry, depthMaterial ) {
33847 this.onBeforeRender( renderer,
null, shadowCamera, geometry, depthMaterial );
33855 constructor( parameters ) {
33859 this.isLineBasicMaterial =
true;
33861 this.type =
'LineBasicMaterial';
33863 this.color =
new Color( 0xffffff );
33867 this.linewidth = 1;
33868 this.linecap =
'round';
33869 this.linejoin =
'round';
33873 this.setValues( parameters );
33880 super.copy( source );
33882 this.color.copy( source.color );
33884 this.map = source.map;
33886 this.linewidth = source.linewidth;
33887 this.linecap = source.linecap;
33888 this.linejoin = source.linejoin;
33890 this.fog = source.fog;
33898 const _start$1 =
new Vector3();
33899 const _end$1 =
new Vector3();
33900 const _inverseMatrix$1 =
new Matrix4();
33901 const _ray$1 =
new Ray();
33902 const _sphere$1 =
new Sphere();
33910 this.isLine =
true;
33912 this.type =
'Line';
33914 this.geometry = geometry;
33915 this.material = material;
33921 copy( source, recursive ) {
33923 super.copy( source, recursive );
33925 this.material =
Array.isArray( source.material ) ? source.material.slice() : source.material;
33926 this.geometry = source.geometry;
33932 computeLineDistances() {
33934 const geometry = this.geometry;
33938 if ( geometry.index ===
null ) {
33940 const positionAttribute = geometry.attributes.position;
33941 const lineDistances = [ 0 ];
33943 for ( let
i = 1,
l = positionAttribute.count;
i <
l;
i ++ ) {
33945 _start$1.fromBufferAttribute( positionAttribute,
i - 1 );
33946 _end$1.fromBufferAttribute( positionAttribute,
i );
33948 lineDistances[
i ] = lineDistances[
i - 1 ];
33949 lineDistances[
i ] += _start$1.distanceTo( _end$1 );
33953 geometry.setAttribute(
'lineDistance',
new Float32BufferAttribute( lineDistances, 1 ) );
33957 console.warn(
'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
33965 raycast( raycaster, intersects ) {
33967 const geometry = this.geometry;
33968 const matrixWorld = this.matrixWorld;
33969 const threshold = raycaster.params.Line.threshold;
33970 const drawRange = geometry.drawRange;
33974 if ( geometry.boundingSphere ===
null ) geometry.computeBoundingSphere();
33976 _sphere$1.copy( geometry.boundingSphere );
33977 _sphere$1.applyMatrix4( matrixWorld );
33978 _sphere$1.radius += threshold;
33980 if ( raycaster.ray.intersectsSphere( _sphere$1 ) ===
false )
return;
33984 _inverseMatrix$1.copy( matrixWorld ).invert();
33985 _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 );
33987 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
33988 const localThresholdSq = localThreshold * localThreshold;
33990 const vStart =
new Vector3();
33992 const interSegment =
new Vector3();
33993 const interRay =
new Vector3();
33994 const step = this.isLineSegments ? 2 : 1;
33996 const index = geometry.index;
33997 const attributes = geometry.attributes;
33998 const positionAttribute = attributes.position;
34000 if ( index !==
null ) {
34002 const start =
Math.max( 0, drawRange.start );
34003 const end =
Math.min( index.count, ( drawRange.start + drawRange.count ) );
34005 for ( let
i = start,
l = end - 1;
i <
l;
i += step ) {
34007 const a = index.getX(
i );
34008 const b = index.getX(
i + 1 );
34010 vStart.fromBufferAttribute( positionAttribute,
a );
34011 vEnd.fromBufferAttribute( positionAttribute,
b );
34013 const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
34015 if ( distSq > localThresholdSq )
continue;
34017 interRay.applyMatrix4( this.matrixWorld );
34019 const distance = raycaster.ray.origin.distanceTo( interRay );
34021 if ( distance < raycaster.near || distance > raycaster.far )
continue;
34025 distance: distance,
34028 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
34040 const start =
Math.max( 0, drawRange.start );
34041 const end =
Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
34043 for ( let
i = start,
l = end - 1;
i <
l;
i += step ) {
34045 vStart.fromBufferAttribute( positionAttribute,
i );
34046 vEnd.fromBufferAttribute( positionAttribute,
i + 1 );
34048 const distSq = _ray$1.distanceSqToSegment( vStart, vEnd, interRay, interSegment );
34050 if ( distSq > localThresholdSq )
continue;
34052 interRay.applyMatrix4( this.matrixWorld );
34054 const distance = raycaster.ray.origin.distanceTo( interRay );
34056 if ( distance < raycaster.near || distance > raycaster.far )
continue;
34060 distance: distance,
34063 point: interSegment.clone().applyMatrix4( this.matrixWorld ),
34079 const geometry = this.geometry;
34081 const morphAttributes = geometry.morphAttributes;
34082 const keys = Object.keys( morphAttributes );
34084 if ( keys.length > 0 ) {
34086 const morphAttribute = morphAttributes[ keys[ 0 ] ];
34090 this.morphTargetInfluences = [];
34091 this.morphTargetDictionary = {};
34093 for ( let
m = 0, ml = morphAttribute.length;
m < ml;
m ++ ) {
34095 const name = morphAttribute[
m ].name ||
String(
m );
34097 this.morphTargetInfluences.push( 0 );
34098 this.morphTargetDictionary[ name ] =
m;
34110 const _start =
new Vector3();
34113 class LineSegments
extends Line {
34115 constructor( geometry, material ) {
34117 super( geometry, material );
34119 this.isLineSegments =
true;
34121 this.type =
'LineSegments';
34125 computeLineDistances() {
34127 const geometry = this.geometry;
34131 if ( geometry.index ===
null ) {
34133 const positionAttribute = geometry.attributes.position;
34134 const lineDistances = [];
34136 for ( let
i = 0,
l = positionAttribute.count;
i <
l;
i += 2 ) {
34138 _start.fromBufferAttribute( positionAttribute,
i );
34139 _end.fromBufferAttribute( positionAttribute,
i + 1 );
34141 lineDistances[
i ] = (
i === 0 ) ? 0 : lineDistances[
i - 1 ];
34142 lineDistances[
i + 1 ] = lineDistances[
i ] + _start.distanceTo( _end );
34146 geometry.setAttribute(
'lineDistance',
new Float32BufferAttribute( lineDistances, 1 ) );
34150 console.warn(
'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' );
34160 class LineLoop
extends Line {
34162 constructor( geometry, material ) {
34164 super( geometry, material );
34166 this.isLineLoop =
true;
34168 this.type =
'LineLoop';
34174 class PointsMaterial
extends Material {
34176 constructor( parameters ) {
34180 this.isPointsMaterial =
true;
34182 this.type =
'PointsMaterial';
34184 this.color =
new Color( 0xffffff );
34188 this.alphaMap =
null;
34191 this.sizeAttenuation =
true;
34195 this.setValues( parameters );
34201 super.copy( source );
34203 this.color.copy( source.color );
34205 this.map = source.map;
34207 this.alphaMap = source.alphaMap;
34209 this.size = source.size;
34210 this.sizeAttenuation = source.sizeAttenuation;
34212 this.fog = source.fog;
34220 const _inverseMatrix =
new Matrix4();
34221 const _ray =
new Ray();
34222 const _sphere =
new Sphere();
34223 const _position$2 =
new Vector3();
34227 constructor( geometry =
new BufferGeometry(), material =
new PointsMaterial() ) {
34231 this.isPoints =
true;
34233 this.type =
'Points';
34235 this.geometry = geometry;
34236 this.material = material;
34242 copy( source, recursive ) {
34244 super.copy( source, recursive );
34246 this.material =
Array.isArray( source.material ) ? source.material.slice() : source.material;
34247 this.geometry = source.geometry;
34253 raycast( raycaster, intersects ) {
34255 const geometry = this.geometry;
34256 const matrixWorld = this.matrixWorld;
34257 const threshold = raycaster.params.Points.threshold;
34258 const drawRange = geometry.drawRange;
34262 if ( geometry.boundingSphere ===
null ) geometry.computeBoundingSphere();
34264 _sphere.copy( geometry.boundingSphere );
34265 _sphere.applyMatrix4( matrixWorld );
34266 _sphere.radius += threshold;
34268 if ( raycaster.ray.intersectsSphere( _sphere ) ===
false )
return;
34272 _inverseMatrix.copy( matrixWorld ).invert();
34273 _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix );
34275 const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 );
34276 const localThresholdSq = localThreshold * localThreshold;
34278 const index = geometry.index;
34279 const attributes = geometry.attributes;
34280 const positionAttribute = attributes.position;
34282 if ( index !==
null ) {
34284 const start =
Math.max( 0, drawRange.start );
34285 const end =
Math.min( index.count, ( drawRange.start + drawRange.count ) );
34287 for ( let
i = start, il = end;
i < il;
i ++ ) {
34289 const a = index.getX(
i );
34291 _position$2.fromBufferAttribute( positionAttribute,
a );
34293 testPoint( _position$2,
a, localThresholdSq, matrixWorld, raycaster, intersects,
this );
34299 const start =
Math.max( 0, drawRange.start );
34300 const end =
Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) );
34302 for ( let
i = start,
l = end;
i <
l;
i ++ ) {
34304 _position$2.fromBufferAttribute( positionAttribute,
i );
34306 testPoint( _position$2,
i, localThresholdSq, matrixWorld, raycaster, intersects,
this );
34316 const geometry = this.geometry;
34318 const morphAttributes = geometry.morphAttributes;
34319 const keys = Object.keys( morphAttributes );
34321 if ( keys.length > 0 ) {
34323 const morphAttribute = morphAttributes[ keys[ 0 ] ];
34327 this.morphTargetInfluences = [];
34328 this.morphTargetDictionary = {};
34330 for ( let
m = 0, ml = morphAttribute.length;
m < ml;
m ++ ) {
34332 const name = morphAttribute[
m ].name ||
String(
m );
34334 this.morphTargetInfluences.push( 0 );
34335 this.morphTargetDictionary[ name ] =
m;
34347 function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects,
object ) {
34349 const rayPointDistanceSq = _ray.distanceSqToPoint( point );
34351 if ( rayPointDistanceSq < localThresholdSq ) {
34353 const intersectPoint =
new Vector3();
34355 _ray.closestPointToPoint( point, intersectPoint );
34356 intersectPoint.applyMatrix4( matrixWorld );
34358 const distance = raycaster.ray.origin.distanceTo( intersectPoint );
34360 if ( distance < raycaster.near || distance > raycaster.far )
return;
34364 distance: distance,
34365 distanceToRay:
Math.sqrt( rayPointDistanceSq ),
34366 point: intersectPoint,
34377 class VideoTexture
extends Texture {
34379 constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
34381 super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
34383 this.isVideoTexture =
true;
34388 this.generateMipmaps =
false;
34390 const scope =
this;
34392 function updateVideo() {
34394 scope.needsUpdate =
true;
34395 video.requestVideoFrameCallback( updateVideo );
34399 if (
'requestVideoFrameCallback' in video ) {
34401 video.requestVideoFrameCallback( updateVideo );
34409 return new this.constructor( this.image ).copy(
this );
34415 const video = this.image;
34416 const hasVideoFrameCallback =
'requestVideoFrameCallback' in video;
34418 if ( hasVideoFrameCallback ===
false && video.readyState >= video.HAVE_CURRENT_DATA ) {
34420 this.needsUpdate =
true;
34428 class FramebufferTexture
extends Texture {
34430 constructor( width, height ) {
34432 super( { width, height } );
34434 this.isFramebufferTexture =
true;
34439 this.generateMipmaps =
false;
34441 this.needsUpdate =
true;
34449 constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) {
34451 super(
null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace );
34453 this.isCompressedTexture =
true;
34455 this.image = { width: width, height: height };
34456 this.mipmaps = mipmaps;
34461 this.flipY =
false;
34466 this.generateMipmaps =
false;
34474 constructor( mipmaps, width, height, depth, format, type ) {
34476 super( mipmaps, width, height, format, type );
34478 this.isCompressedArrayTexture =
true;
34479 this.image.depth = depth;
34488 constructor( images, format, type ) {
34492 this.isCompressedCubeTexture =
true;
34493 this.isCubeTexture =
true;
34495 this.image = images;
34501 class CanvasTexture
extends Texture {
34503 constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
34505 super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
34507 this.isCanvasTexture =
true;
34509 this.needsUpdate =
true;
34549 this.type =
'Curve';
34551 this.arcLengthDivisions = 200;
34560 console.warn(
'THREE.Curve: .getPoint() not implemented.' );
34571 return this.
getPoint(
t, optionalTarget );
34581 for ( let
d = 0;
d <= divisions;
d ++ ) {
34583 points.push( this.
getPoint(
d / divisions ) );
34597 for ( let
d = 0;
d <= divisions;
d ++ ) {
34612 return lengths[ lengths.length - 1 ];
34618 getLengths( divisions = this.arcLengthDivisions ) {
34620 if ( this.cacheArcLengths &&
34621 ( this.cacheArcLengths.length === divisions + 1 ) &&
34622 !
this.needsUpdate ) {
34624 return this.cacheArcLengths;
34628 this.needsUpdate =
false;
34631 let current, last = this.
getPoint( 0 );
34636 for ( let
p = 1;
p <= divisions;
p ++ ) {
34638 current = this.
getPoint(
p / divisions );
34639 sum += current.distanceTo( last );
34645 this.cacheArcLengths =
cache;
34653 this.needsUpdate =
true;
34665 const il = arcLengths.length;
34667 let targetArcLength;
34671 targetArcLength = distance;
34675 targetArcLength =
u * arcLengths[ il - 1 ];
34681 let low = 0, high = il - 1, comparison;
34683 while ( low <= high ) {
34685 i =
Math.floor( low + ( high - low ) / 2 );
34687 comparison = arcLengths[
i ] - targetArcLength;
34689 if ( comparison < 0 ) {
34693 }
else if ( comparison > 0 ) {
34710 if ( arcLengths[
i ] === targetArcLength ) {
34712 return i / ( il - 1 );
34718 const lengthBefore = arcLengths[
i ];
34719 const lengthAfter = arcLengths[
i + 1 ];
34721 const segmentLength = lengthAfter - lengthBefore;
34725 const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
34729 const t = (
i + segmentFraction ) / ( il - 1 );
34742 const delta = 0.0001;
34743 let t1 =
t - delta;
34744 let t2 =
t + delta;
34748 if ( t1 < 0 ) t1 = 0;
34749 if ( t2 > 1 ) t2 = 1;
34754 const tangent = optionalTarget || ( ( pt1.isVector2 ) ?
new Vector2() : new
Vector3() );
34756 tangent.copy( pt2 ).sub( pt1 ).normalize();
34769 computeFrenetFrames( segments, closed ) {
34775 const tangents = [];
34776 const normals = [];
34777 const binormals = [];
34784 for ( let
i = 0;
i <= segments;
i ++ ) {
34786 const u =
i / segments;
34795 normals[ 0 ] =
new Vector3();
34796 binormals[ 0 ] =
new Vector3();
34798 const tx =
Math.abs( tangents[ 0 ].
x );
34799 const ty =
Math.abs( tangents[ 0 ].
y );
34800 const tz =
Math.abs( tangents[ 0 ].
z );
34822 vec.crossVectors( tangents[ 0 ],
normal ).normalize();
34824 normals[ 0 ].crossVectors( tangents[ 0 ], vec );
34825 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
34830 for ( let
i = 1;
i <= segments;
i ++ ) {
34832 normals[
i ] = normals[
i - 1 ].clone();
34834 binormals[
i ] = binormals[
i - 1 ].clone();
34836 vec.crossVectors( tangents[
i - 1 ], tangents[
i ] );
34838 if ( vec.length() >
Number.EPSILON ) {
34842 const theta =
Math.acos( clamp( tangents[
i - 1 ].dot( tangents[
i ] ), - 1, 1 ) );
34844 normals[
i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
34848 binormals[
i ].crossVectors( tangents[
i ], normals[
i ] );
34854 if ( closed ===
true ) {
34856 let theta =
Math.acos( clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
34859 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
34865 for ( let
i = 1;
i <= segments;
i ++ ) {
34868 normals[
i ].applyMatrix4( mat.makeRotationAxis( tangents[
i ], theta *
i ) );
34869 binormals[
i ].crossVectors( tangents[
i ], normals[
i ] );
34876 tangents: tangents,
34878 binormals: binormals
34885 return new this.constructor().copy(
this );
34891 this.arcLengthDivisions = source.arcLengthDivisions;
34903 generator:
'Curve.toJSON'
34907 data.arcLengthDivisions = this.arcLengthDivisions;
34908 data.type = this.type;
34916 this.arcLengthDivisions = json.arcLengthDivisions;
34926 constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle =
Math.PI * 2, aClockwise =
false, aRotation = 0 ) {
34930 this.isEllipseCurve =
true;
34932 this.type =
'EllipseCurve';
34937 this.xRadius = xRadius;
34938 this.yRadius = yRadius;
34940 this.aStartAngle = aStartAngle;
34941 this.aEndAngle = aEndAngle;
34943 this.aClockwise = aClockwise;
34945 this.aRotation = aRotation;
34951 const point = optionalTarget ||
new Vector2();
34953 const twoPi =
Math.PI * 2;
34954 let deltaAngle = this.aEndAngle - this.aStartAngle;
34955 const samePoints =
Math.abs( deltaAngle ) <
Number.EPSILON;
34958 while ( deltaAngle < 0 ) deltaAngle += twoPi;
34959 while ( deltaAngle > twoPi ) deltaAngle -= twoPi;
34961 if ( deltaAngle <
Number.EPSILON ) {
34963 if ( samePoints ) {
34969 deltaAngle = twoPi;
34975 if ( this.aClockwise ===
true && ! samePoints ) {
34977 if ( deltaAngle === twoPi ) {
34979 deltaAngle = - twoPi;
34983 deltaAngle = deltaAngle - twoPi;
34989 const angle = this.aStartAngle +
t * deltaAngle;
34990 let
x = this.aX + this.xRadius *
Math.cos( angle );
34991 let
y = this.aY + this.yRadius *
Math.sin( angle );
34993 if ( this.aRotation !== 0 ) {
34995 const cos =
Math.cos( this.aRotation );
34996 const sin =
Math.sin( this.aRotation );
34998 const tx =
x - this.aX;
34999 const ty =
y - this.aY;
35002 x = tx * cos - ty * sin + this.aX;
35003 y = tx * sin + ty * cos + this.aY;
35007 return point.set(
x,
y );
35013 super.copy( source );
35015 this.aX = source.aX;
35016 this.aY = source.aY;
35018 this.xRadius = source.xRadius;
35019 this.yRadius = source.yRadius;
35021 this.aStartAngle = source.aStartAngle;
35022 this.aEndAngle = source.aEndAngle;
35024 this.aClockwise = source.aClockwise;
35026 this.aRotation = source.aRotation;
35034 const data = super.toJSON();
35039 data.xRadius = this.xRadius;
35040 data.yRadius = this.yRadius;
35042 data.aStartAngle = this.aStartAngle;
35043 data.aEndAngle = this.aEndAngle;
35045 data.aClockwise = this.aClockwise;
35047 data.aRotation = this.aRotation;
35055 super.fromJSON( json );
35060 this.xRadius = json.xRadius;
35061 this.yRadius = json.yRadius;
35063 this.aStartAngle = json.aStartAngle;
35064 this.aEndAngle = json.aEndAngle;
35066 this.aClockwise = json.aClockwise;
35068 this.aRotation = json.aRotation;
35078 constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
35080 super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
35082 this.isArcCurve =
true;
35084 this.type =
'ArcCurve';
35110 function CubicPoly() {
35112 let c0 = 0, c1 = 0, c2 = 0, c3 = 0;
35122 function init( x0, x1, t0, t1 ) {
35126 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1;
35127 c3 = 2 * x0 - 2 * x1 + t0 + t1;
35133 initCatmullRom:
function ( x0, x1, x2, x3, tension ) {
35135 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) );
35139 initNonuniformCatmullRom:
function ( x0, x1, x2, x3, dt0, dt1, dt2 ) {
35142 let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1;
35143 let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2;
35149 init( x1, x2, t1, t2 );
35153 calc:
function (
t ) {
35157 return c0 + c1 *
t + c2 * t2 + c3 * t3;
35168 const px =
new CubicPoly();
35169 const py =
new CubicPoly();
35170 const pz =
new CubicPoly();
35172 class CatmullRomCurve3
extends Curve {
35174 constructor( points = [], closed =
false, curveType =
'centripetal', tension = 0.5 ) {
35178 this.isCatmullRomCurve3 =
true;
35180 this.type =
'CatmullRomCurve3';
35182 this.points = points;
35183 this.closed = closed;
35184 this.curveType = curveType;
35185 this.tension = tension;
35191 const point = optionalTarget;
35193 const points = this.points;
35194 const l = points.length;
35196 const p = (
l - ( this.closed ? 0 : 1 ) ) *
t;
35197 let intPoint =
Math.floor(
p );
35198 let weight =
p - intPoint;
35200 if ( this.closed ) {
35202 intPoint += intPoint > 0 ? 0 : (
Math.floor(
Math.abs( intPoint ) /
l ) + 1 ) *
l;
35204 }
else if ( weight === 0 && intPoint ===
l - 1 ) {
35213 if ( this.closed || intPoint > 0 ) {
35215 p0 = points[ ( intPoint - 1 ) %
l ];
35220 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] );
35225 const p1 = points[ intPoint %
l ];
35226 const p2 = points[ ( intPoint + 1 ) %
l ];
35228 if ( this.closed || intPoint + 2 <
l ) {
35230 p3 = points[ ( intPoint + 2 ) %
l ];
35235 tmp.subVectors( points[
l - 1 ], points[
l - 2 ] ).add( points[
l - 1 ] );
35240 if ( this.curveType ===
'centripetal' || this.curveType ===
'chordal' ) {
35243 const pow = this.curveType ===
'chordal' ? 0.5 : 0.25;
35244 let dt0 =
Math.pow( p0.distanceToSquared( p1 ),
pow );
35245 let dt1 =
Math.pow( p1.distanceToSquared( p2 ),
pow );
35246 let dt2 =
Math.pow( p2.distanceToSquared( p3 ),
pow );
35249 if ( dt1 < 1
e-4 ) dt1 = 1.0;
35250 if ( dt0 < 1
e-4 ) dt0 = dt1;
35251 if ( dt2 < 1
e-4 ) dt2 = dt1;
35253 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 );
35254 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 );
35255 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 );
35257 }
else if ( this.curveType ===
'catmullrom' ) {
35259 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x,
this.tension );
35260 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y,
this.tension );
35261 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z,
this.tension );
35277 super.copy( source );
35281 for ( let
i = 0,
l = source.points.length;
i <
l;
i ++ ) {
35283 const point = source.points[
i ];
35285 this.points.push( point.clone() );
35289 this.closed = source.closed;
35290 this.curveType = source.curveType;
35291 this.tension = source.tension;
35299 const data = super.toJSON();
35303 for ( let
i = 0,
l = this.points.length;
i <
l;
i ++ ) {
35305 const point = this.points[
i ];
35306 data.points.push( point.toArray() );
35310 data.closed = this.closed;
35311 data.curveType = this.curveType;
35312 data.tension = this.tension;
35320 super.fromJSON( json );
35324 for ( let
i = 0,
l = json.points.length;
i <
l;
i ++ ) {
35326 const point = json.points[
i ];
35331 this.closed = json.closed;
35332 this.curveType = json.curveType;
35333 this.tension = json.tension;
35346 function CatmullRom(
t, p0, p1, p2, p3 ) {
35348 const v0 = ( p2 - p0 ) * 0.5;
35349 const v1 = ( p3 - p1 ) * 0.5;
35352 return ( 2 * p1 - 2 * p2 + v0 +
v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 -
v1 ) * t2 + v0 *
t + p1;
35358 function QuadraticBezierP0(
t,
p ) {
35365 function QuadraticBezierP1(
t,
p ) {
35367 return 2 * ( 1 -
t ) *
t *
p;
35371 function QuadraticBezierP2(
t,
p ) {
35377 function QuadraticBezier(
t, p0, p1, p2 ) {
35379 return QuadraticBezierP0(
t, p0 ) + QuadraticBezierP1(
t, p1 ) +
35380 QuadraticBezierP2(
t, p2 );
35386 function CubicBezierP0(
t,
p ) {
35389 return k *
k *
k *
p;
35393 function CubicBezierP1(
t,
p ) {
35396 return 3 *
k *
k *
t *
p;
35400 function CubicBezierP2(
t,
p ) {
35402 return 3 * ( 1 -
t ) *
t *
t *
p;
35406 function CubicBezierP3(
t,
p ) {
35408 return t *
t *
t *
p;
35412 function CubicBezier(
t, p0, p1, p2, p3 ) {
35414 return CubicBezierP0(
t, p0 ) + CubicBezierP1(
t, p1 ) + CubicBezierP2(
t, p2 ) +
35415 CubicBezierP3(
t, p3 );
35425 this.isCubicBezierCurve =
true;
35427 this.type =
'CubicBezierCurve';
35438 const point = optionalTarget;
35440 const v0 = this.v0,
v1 = this.
v1,
v2 = this.
v2,
v3 = this.
v3;
35443 CubicBezier(
t, v0.x,
v1.x,
v2.x,
v3.x ),
35444 CubicBezier(
t, v0.y,
v1.y,
v2.y,
v3.y )
35453 super.copy( source );
35455 this.v0.copy( source.v0 );
35456 this.
v1.copy( source.v1 );
35457 this.
v2.copy( source.v2 );
35458 this.
v3.copy( source.v3 );
35466 const data = super.toJSON();
35468 data.v0 = this.v0.toArray();
35469 data.v1 = this.
v1.toArray();
35470 data.v2 = this.
v2.toArray();
35471 data.v3 = this.
v3.toArray();
35479 super.fromJSON( json );
35481 this.v0.fromArray( json.v0 );
35482 this.
v1.fromArray( json.v1 );
35483 this.
v2.fromArray( json.v2 );
35484 this.
v3.fromArray( json.v3 );
35498 this.isCubicBezierCurve3 =
true;
35500 this.type =
'CubicBezierCurve3';
35511 const point = optionalTarget;
35513 const v0 = this.v0,
v1 = this.
v1,
v2 = this.
v2,
v3 = this.
v3;
35516 CubicBezier(
t, v0.x,
v1.x,
v2.x,
v3.x ),
35517 CubicBezier(
t, v0.y,
v1.y,
v2.y,
v3.y ),
35518 CubicBezier(
t, v0.z,
v1.z,
v2.z,
v3.z )
35527 super.copy( source );
35529 this.v0.copy( source.v0 );
35530 this.
v1.copy( source.v1 );
35531 this.
v2.copy( source.v2 );
35532 this.
v3.copy( source.v3 );
35540 const data = super.toJSON();
35542 data.v0 = this.v0.toArray();
35543 data.v1 = this.
v1.toArray();
35544 data.v2 = this.
v2.toArray();
35545 data.v3 = this.
v3.toArray();
35553 super.fromJSON( json );
35555 this.v0.fromArray( json.v0 );
35556 this.
v1.fromArray( json.v1 );
35557 this.
v2.fromArray( json.v2 );
35558 this.
v3.fromArray( json.v3 );
35572 this.isLineCurve =
true;
35574 this.type =
'LineCurve';
35583 const point = optionalTarget;
35587 point.copy( this.
v2 );
35591 point.copy( this.
v2 ).sub( this.
v1 );
35592 point.multiplyScalar(
t ).add( this.
v1 );
35603 return this.
getPoint(
u, optionalTarget );
35609 return optionalTarget.subVectors( this.
v2, this.
v1 ).normalize();
35621 super.copy( source );
35623 this.
v1.copy( source.v1 );
35624 this.
v2.copy( source.v2 );
35632 const data = super.toJSON();
35634 data.v1 = this.
v1.toArray();
35635 data.v2 = this.
v2.toArray();
35643 super.fromJSON( json );
35645 this.
v1.fromArray( json.v1 );
35646 this.
v2.fromArray( json.v2 );
35660 this.isLineCurve3 =
true;
35662 this.type =
'LineCurve3';
35671 const point = optionalTarget;
35675 point.copy( this.
v2 );
35679 point.copy( this.
v2 ).sub( this.
v1 );
35680 point.multiplyScalar(
t ).add( this.
v1 );
35691 return this.
getPoint(
u, optionalTarget );
35697 return optionalTarget.subVectors( this.
v2, this.
v1 ).normalize();
35709 super.copy( source );
35711 this.
v1.copy( source.v1 );
35712 this.
v2.copy( source.v2 );
35720 const data = super.toJSON();
35722 data.v1 = this.
v1.toArray();
35723 data.v2 = this.
v2.toArray();
35731 super.fromJSON( json );
35733 this.
v1.fromArray( json.v1 );
35734 this.
v2.fromArray( json.v2 );
35748 this.isQuadraticBezierCurve =
true;
35750 this.type =
'QuadraticBezierCurve';
35760 const point = optionalTarget;
35762 const v0 = this.v0,
v1 = this.
v1,
v2 = this.
v2;
35765 QuadraticBezier(
t, v0.x,
v1.x,
v2.x ),
35766 QuadraticBezier(
t, v0.y,
v1.y,
v2.y )
35775 super.copy( source );
35777 this.v0.copy( source.v0 );
35778 this.
v1.copy( source.v1 );
35779 this.
v2.copy( source.v2 );
35787 const data = super.toJSON();
35789 data.v0 = this.v0.toArray();
35790 data.v1 = this.
v1.toArray();
35791 data.v2 = this.
v2.toArray();
35799 super.fromJSON( json );
35801 this.v0.fromArray( json.v0 );
35802 this.
v1.fromArray( json.v1 );
35803 this.
v2.fromArray( json.v2 );
35817 this.isQuadraticBezierCurve3 =
true;
35819 this.type =
'QuadraticBezierCurve3';
35829 const point = optionalTarget;
35831 const v0 = this.v0,
v1 = this.
v1,
v2 = this.
v2;
35834 QuadraticBezier(
t, v0.x,
v1.x,
v2.x ),
35835 QuadraticBezier(
t, v0.y,
v1.y,
v2.y ),
35836 QuadraticBezier(
t, v0.z,
v1.z,
v2.z )
35845 super.copy( source );
35847 this.v0.copy( source.v0 );
35848 this.
v1.copy( source.v1 );
35849 this.
v2.copy( source.v2 );
35857 const data = super.toJSON();
35859 data.v0 = this.v0.toArray();
35860 data.v1 = this.
v1.toArray();
35861 data.v2 = this.
v2.toArray();
35869 super.fromJSON( json );
35871 this.v0.fromArray( json.v0 );
35872 this.
v1.fromArray( json.v1 );
35873 this.
v2.fromArray( json.v2 );
35883 constructor( points = [] ) {
35887 this.isSplineCurve =
true;
35889 this.type =
'SplineCurve';
35891 this.points = points;
35897 const point = optionalTarget;
35899 const points = this.points;
35900 const p = ( points.length - 1 ) *
t;
35902 const intPoint =
Math.floor(
p );
35903 const weight =
p - intPoint;
35905 const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ];
35906 const p1 = points[ intPoint ];
35907 const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ];
35908 const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ];
35911 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ),
35912 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y )
35921 super.copy( source );
35925 for ( let
i = 0,
l = source.points.length;
i <
l;
i ++ ) {
35927 const point = source.points[
i ];
35929 this.points.push( point.clone() );
35939 const data = super.toJSON();
35943 for ( let
i = 0,
l = this.points.length;
i <
l;
i ++ ) {
35945 const point = this.points[
i ];
35946 data.points.push( point.toArray() );
35956 super.fromJSON( json );
35960 for ( let
i = 0,
l = json.points.length;
i <
l;
i ++ ) {
35962 const point = json.points[
i ];
35973 var Curves = Object.freeze({
35976 CatmullRomCurve3: CatmullRomCurve3,
35998 this.type =
'CurvePath';
36001 this.autoClose =
false;
36007 this.curves.push( curve );
36014 const startPoint = this.curves[ 0 ].getPoint( 0 );
36015 const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
36017 if ( ! startPoint.equals( endPoint ) ) {
36019 const lineType = ( startPoint.isVector2 === true ) ?
'LineCurve' :
'LineCurve3';
36020 this.curves.push(
new Curves[ lineType ]( endPoint, startPoint ) );
36045 while (
i < curveLengths.length ) {
36047 if ( curveLengths[
i ] >=
d ) {
36049 const diff = curveLengths[
i ] -
d;
36050 const curve = this.curves[
i ];
36052 const segmentLength = curve.getLength();
36053 const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
36055 return curve.getPointAt(
u, optionalTarget );
36076 return lens[ lens.length - 1 ];
36083 this.needsUpdate =
true;
36084 this.cacheLengths =
null;
36096 if ( this.cacheLengths && this.cacheLengths.length ===
this.curves.length ) {
36098 return this.cacheLengths;
36105 const lengths = [];
36108 for ( let
i = 0,
l = this.curves.length;
i <
l;
i ++ ) {
36110 sums += this.curves[
i ].getLength();
36111 lengths.push( sums );
36115 this.cacheLengths = lengths;
36125 for ( let
i = 0;
i <= divisions;
i ++ ) {
36127 points.push( this.
getPoint(
i / divisions ) );
36131 if ( this.autoClose ) {
36133 points.push( points[ 0 ] );
36146 for ( let
i = 0, curves = this.curves;
i < curves.length;
i ++ ) {
36148 const curve = curves[
i ];
36149 const resolution = curve.isEllipseCurve ? divisions * 2
36150 : ( curve.isLineCurve || curve.isLineCurve3 ) ? 1
36151 : curve.isSplineCurve ? divisions * curve.points.length
36154 const pts = curve.getPoints( resolution );
36156 for ( let
j = 0;
j < pts.length;
j ++ ) {
36158 const point = pts[
j ];
36160 if ( last && last.equals( point ) )
continue;
36162 points.push( point );
36169 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
36171 points.push( points[ 0 ] );
36181 super.copy( source );
36185 for ( let
i = 0,
l = source.curves.length;
i <
l;
i ++ ) {
36187 const curve = source.curves[
i ];
36189 this.curves.push( curve.clone() );
36193 this.autoClose = source.autoClose;
36201 const data = super.toJSON();
36203 data.autoClose = this.autoClose;
36206 for ( let
i = 0,
l = this.curves.length;
i <
l;
i ++ ) {
36208 const curve = this.curves[
i ];
36209 data.curves.push( curve.toJSON() );
36219 super.fromJSON( json );
36221 this.autoClose = json.autoClose;
36224 for ( let
i = 0,
l = json.curves.length;
i <
l;
i ++ ) {
36226 const curve = json.curves[
i ];
36227 this.curves.push(
new Curves[ curve.type ]().fromJSON( curve ) );
36239 constructor( points ) {
36243 this.type =
'Path';
36245 this.currentPoint =
new Vector2();
36249 this.setFromPoints( points );
36255 setFromPoints( points ) {
36257 this.
moveTo( points[ 0 ].
x, points[ 0 ].
y );
36259 for ( let
i = 1,
l = points.length;
i <
l;
i ++ ) {
36261 this.
lineTo( points[
i ].
x, points[
i ].
y );
36271 this.currentPoint.set(
x,
y );
36280 this.curves.push( curve );
36282 this.currentPoint.set(
x,
y );
36291 this.currentPoint.clone(),
36296 this.curves.push( curve );
36298 this.currentPoint.set( aX, aY );
36307 this.currentPoint.clone(),
36313 this.curves.push( curve );
36315 this.currentPoint.set( aX, aY );
36323 const npts = [ this.currentPoint.clone() ].concat( pts );
36326 this.curves.push( curve );
36328 this.currentPoint.copy( pts[ pts.length - 1 ] );
36334 arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36336 const x0 = this.currentPoint.x;
36337 const y0 = this.currentPoint.y;
36339 this.
absarc( aX + x0, aY + y0, aRadius,
36340 aStartAngle, aEndAngle, aClockwise );
36346 absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
36348 this.
absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
36354 ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36356 const x0 = this.currentPoint.x;
36357 const y0 = this.currentPoint.y;
36359 this.
absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36365 absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
36367 const curve =
new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
36369 if ( this.curves.length > 0 ) {
36372 const firstPoint = curve.getPoint( 0 );
36374 if ( ! firstPoint.equals(
this.currentPoint ) ) {
36376 this.
lineTo( firstPoint.x, firstPoint.y );
36382 this.curves.push( curve );
36384 const lastPoint = curve.getPoint( 1 );
36385 this.currentPoint.copy( lastPoint );
36393 super.copy( source );
36395 this.currentPoint.copy( source.currentPoint );
36403 const data = super.toJSON();
36405 data.currentPoint = this.currentPoint.toArray();
36413 super.fromJSON( json );
36415 this.currentPoint.fromArray( json.currentPoint );
36425 constructor( points = [
new Vector2( 0, - 0.5 ),
new Vector2( 0.5, 0 ),
new Vector2( 0, 0.5 ) ], segments = 12, phiStart = 0, phiLength =
Math.PI * 2 ) {
36429 this.type =
'LatheGeometry';
36431 this.parameters = {
36433 segments: segments,
36434 phiStart: phiStart,
36435 phiLength: phiLength
36438 segments =
Math.floor( segments );
36442 phiLength = clamp( phiLength, 0,
Math.PI * 2 );
36446 const indices = [];
36447 const vertices = [];
36449 const initNormals = [];
36450 const normals = [];
36454 const inverseSegments = 1.0 / segments;
36455 const vertex =
new Vector3();
36458 const curNormal =
new Vector3();
36459 const prevNormal =
new Vector3();
36465 for ( let
j = 0;
j <= ( points.length - 1 );
j ++ ) {
36471 dx = points[
j + 1 ].x - points[
j ].x;
36472 dy = points[
j + 1 ].y - points[
j ].y;
36478 prevNormal.copy(
normal );
36486 case ( points.length - 1 ):
36488 initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z );
36494 dx = points[
j + 1 ].x - points[
j ].x;
36495 dy = points[
j + 1 ].y - points[
j ].y;
36501 curNormal.copy(
normal );
36503 normal.x += prevNormal.x;
36504 normal.y += prevNormal.y;
36505 normal.z += prevNormal.z;
36511 prevNormal.copy( curNormal );
36519 for ( let
i = 0;
i <= segments;
i ++ ) {
36521 const phi = phiStart +
i * inverseSegments * phiLength;
36523 const sin =
Math.sin( phi );
36524 const cos =
Math.cos( phi );
36526 for ( let
j = 0;
j <= ( points.length - 1 );
j ++ ) {
36530 vertex.x = points[
j ].x * sin;
36531 vertex.y = points[
j ].y;
36532 vertex.z = points[
j ].x * cos;
36534 vertices.push( vertex.x, vertex.y, vertex.z );
36538 uv.x =
i / segments;
36539 uv.y =
j / ( points.length - 1 );
36541 uvs.push( uv.x, uv.y );
36545 const x = initNormals[ 3 *
j + 0 ] * sin;
36546 const y = initNormals[ 3 *
j + 1 ];
36547 const z = initNormals[ 3 *
j + 0 ] * cos;
36549 normals.push(
x,
y,
z );
36557 for ( let
i = 0;
i < segments;
i ++ ) {
36559 for ( let
j = 0;
j < ( points.length - 1 );
j ++ ) {
36561 const base =
j +
i * points.length;
36564 const b = base + points.length;
36565 const c = base + points.length + 1;
36566 const d = base + 1;
36570 indices.push(
a,
b,
d );
36571 indices.push(
c,
d,
b );
36579 this.setIndex( indices );
36580 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
36581 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
36582 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
36588 super.copy( source );
36590 this.parameters = Object.assign( {}, source.parameters );
36596 static fromJSON( data ) {
36598 return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength );
36606 constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) {
36608 const path =
new Path();
36609 path.absarc( 0, - length / 2, radius,
Math.PI * 1.5, 0 );
36610 path.absarc( 0, length / 2, radius, 0,
Math.PI * 0.5 );
36612 super( path.getPoints( capSegments ), radialSegments );
36614 this.type =
'CapsuleGeometry';
36616 this.parameters = {
36619 capSegments: capSegments,
36620 radialSegments: radialSegments,
36625 static fromJSON( data ) {
36627 return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments );
36635 constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength =
Math.PI * 2 ) {
36639 this.type =
'CircleGeometry';
36641 this.parameters = {
36643 segments: segments,
36644 thetaStart: thetaStart,
36645 thetaLength: thetaLength
36648 segments =
Math.max( 3, segments );
36652 const indices = [];
36653 const vertices = [];
36654 const normals = [];
36659 const vertex =
new Vector3();
36664 vertices.push( 0, 0, 0 );
36665 normals.push( 0, 0, 1 );
36666 uvs.push( 0.5, 0.5 );
36668 for ( let
s = 0,
i = 3;
s <= segments;
s ++,
i += 3 ) {
36670 const segment = thetaStart +
s / segments * thetaLength;
36674 vertex.x = radius *
Math.cos( segment );
36675 vertex.y = radius *
Math.sin( segment );
36677 vertices.push( vertex.x, vertex.y, vertex.z );
36681 normals.push( 0, 0, 1 );
36685 uv.x = ( vertices[
i ] / radius + 1 ) / 2;
36686 uv.y = ( vertices[
i + 1 ] / radius + 1 ) / 2;
36688 uvs.push( uv.x, uv.y );
36694 for ( let
i = 1;
i <= segments;
i ++ ) {
36696 indices.push(
i,
i + 1, 0 );
36702 this.setIndex( indices );
36703 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
36704 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
36705 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
36711 super.copy( source );
36713 this.parameters = Object.assign( {}, source.parameters );
36719 static fromJSON( data ) {
36721 return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength );
36729 constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded =
false, thetaStart = 0, thetaLength =
Math.PI * 2 ) {
36733 this.type =
'CylinderGeometry';
36735 this.parameters = {
36736 radiusTop: radiusTop,
36737 radiusBottom: radiusBottom,
36739 radialSegments: radialSegments,
36740 heightSegments: heightSegments,
36741 openEnded: openEnded,
36742 thetaStart: thetaStart,
36743 thetaLength: thetaLength
36746 const scope =
this;
36748 radialSegments =
Math.floor( radialSegments );
36749 heightSegments =
Math.floor( heightSegments );
36753 const indices = [];
36754 const vertices = [];
36755 const normals = [];
36761 const indexArray = [];
36762 const halfHeight = height / 2;
36763 let groupStart = 0;
36769 if ( openEnded ===
false ) {
36771 if ( radiusTop > 0 ) generateCap(
true );
36772 if ( radiusBottom > 0 ) generateCap(
false );
36778 this.setIndex( indices );
36779 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
36780 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
36781 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
36783 function generateTorso() {
36786 const vertex =
new Vector3();
36788 let groupCount = 0;
36791 const slope = ( radiusBottom - radiusTop ) / height;
36795 for ( let
y = 0;
y <= heightSegments;
y ++ ) {
36797 const indexRow = [];
36799 const v =
y / heightSegments;
36803 const radius =
v * ( radiusBottom - radiusTop ) + radiusTop;
36805 for ( let
x = 0;
x <= radialSegments;
x ++ ) {
36807 const u =
x / radialSegments;
36809 const theta =
u * thetaLength + thetaStart;
36811 const sinTheta =
Math.sin( theta );
36812 const cosTheta =
Math.cos( theta );
36816 vertex.x = radius * sinTheta;
36817 vertex.y = -
v * height + halfHeight;
36818 vertex.z = radius * cosTheta;
36819 vertices.push( vertex.x, vertex.y, vertex.z );
36823 normal.set( sinTheta, slope, cosTheta ).normalize();
36828 uvs.push(
u, 1 -
v );
36832 indexRow.push( index ++ );
36838 indexArray.push( indexRow );
36844 for ( let
x = 0;
x < radialSegments;
x ++ ) {
36846 for ( let
y = 0;
y < heightSegments;
y ++ ) {
36850 const a = indexArray[
y ][
x ];
36851 const b = indexArray[
y + 1 ][
x ];
36852 const c = indexArray[
y + 1 ][
x + 1 ];
36853 const d = indexArray[
y ][
x + 1 ];
36857 indices.push(
a,
b,
d );
36858 indices.push(
b,
c,
d );
36870 scope.addGroup( groupStart, groupCount, 0 );
36874 groupStart += groupCount;
36878 function generateCap( top ) {
36881 const centerIndexStart = index;
36884 const vertex =
new Vector3();
36886 let groupCount = 0;
36888 const radius = ( top === true ) ? radiusTop : radiusBottom;
36889 const sign = ( top === true ) ? 1 : - 1;
36895 for ( let
x = 1;
x <= radialSegments;
x ++ ) {
36899 vertices.push( 0, halfHeight * sign, 0 );
36903 normals.push( 0, sign, 0 );
36907 uvs.push( 0.5, 0.5 );
36916 const centerIndexEnd = index;
36920 for ( let
x = 0;
x <= radialSegments;
x ++ ) {
36922 const u =
x / radialSegments;
36923 const theta =
u * thetaLength + thetaStart;
36925 const cosTheta =
Math.cos( theta );
36926 const sinTheta =
Math.sin( theta );
36930 vertex.x = radius * sinTheta;
36931 vertex.y = halfHeight * sign;
36932 vertex.z = radius * cosTheta;
36933 vertices.push( vertex.x, vertex.y, vertex.z );
36937 normals.push( 0, sign, 0 );
36941 uv.x = ( cosTheta * 0.5 ) + 0.5;
36942 uv.y = ( sinTheta * 0.5 * sign ) + 0.5;
36943 uvs.push( uv.x, uv.y );
36953 for ( let
x = 0;
x < radialSegments;
x ++ ) {
36955 const c = centerIndexStart +
x;
36956 const i = centerIndexEnd +
x;
36958 if ( top ===
true ) {
36962 indices.push(
i,
i + 1,
c );
36968 indices.push(
i + 1,
i,
c );
36978 scope.addGroup( groupStart, groupCount, top ===
true ? 1 : 2 );
36982 groupStart += groupCount;
36990 super.copy( source );
36992 this.parameters = Object.assign( {}, source.parameters );
36998 static fromJSON( data ) {
37000 return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
37008 constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded =
false, thetaStart = 0, thetaLength =
Math.PI * 2 ) {
37010 super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength );
37012 this.type =
'ConeGeometry';
37014 this.parameters = {
37017 radialSegments: radialSegments,
37018 heightSegments: heightSegments,
37019 openEnded: openEnded,
37020 thetaStart: thetaStart,
37021 thetaLength: thetaLength
37026 static fromJSON( data ) {
37028 return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength );
37036 constructor( vertices = [], indices = [], radius = 1, detail = 0 ) {
37040 this.type =
'PolyhedronGeometry';
37042 this.parameters = {
37043 vertices: vertices,
37051 const vertexBuffer = [];
37052 const uvBuffer = [];
37056 subdivide( detail );
37060 applyRadius( radius );
37068 this.setAttribute(
'position',
new Float32BufferAttribute( vertexBuffer, 3 ) );
37069 this.setAttribute(
'normal',
new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
37070 this.setAttribute(
'uv',
new Float32BufferAttribute( uvBuffer, 2 ) );
37072 if ( detail === 0 ) {
37074 this.computeVertexNormals();
37078 this.normalizeNormals();
37084 function subdivide( detail ) {
37092 for ( let
i = 0;
i < indices.length;
i += 3 ) {
37096 getVertexByIndex( indices[
i + 0 ],
a );
37097 getVertexByIndex( indices[
i + 1 ],
b );
37098 getVertexByIndex( indices[
i + 2 ],
c );
37102 subdivideFace(
a,
b,
c, detail );
37108 function subdivideFace(
a,
b,
c, detail ) {
37110 const cols = detail + 1;
37118 for ( let
i = 0;
i <= cols;
i ++ ) {
37122 const aj =
a.clone().lerp(
c,
i / cols );
37123 const bj =
b.clone().lerp(
c,
i / cols );
37125 const rows = cols -
i;
37127 for ( let
j = 0;
j <= rows;
j ++ ) {
37129 if (
j === 0 &&
i === cols ) {
37135 v[
i ][
j ] = aj.clone().lerp( bj,
j / rows );
37145 for ( let
i = 0;
i < cols;
i ++ ) {
37147 for ( let
j = 0;
j < 2 * ( cols -
i ) - 1;
j ++ ) {
37149 const k =
Math.floor(
j / 2 );
37151 if (
j % 2 === 0 ) {
37153 pushVertex(
v[
i ][
k + 1 ] );
37154 pushVertex(
v[
i + 1 ][
k ] );
37155 pushVertex(
v[
i ][
k ] );
37159 pushVertex(
v[
i ][
k + 1 ] );
37160 pushVertex(
v[
i + 1 ][
k + 1 ] );
37161 pushVertex(
v[
i + 1 ][
k ] );
37171 function applyRadius( radius ) {
37173 const vertex =
new Vector3();
37177 for ( let
i = 0;
i < vertexBuffer.length;
i += 3 ) {
37179 vertex.x = vertexBuffer[
i + 0 ];
37180 vertex.y = vertexBuffer[
i + 1 ];
37181 vertex.z = vertexBuffer[
i + 2 ];
37183 vertex.normalize().multiplyScalar( radius );
37185 vertexBuffer[
i + 0 ] = vertex.x;
37186 vertexBuffer[
i + 1 ] = vertex.y;
37187 vertexBuffer[
i + 2 ] = vertex.z;
37193 function generateUVs() {
37195 const vertex =
new Vector3();
37197 for ( let
i = 0;
i < vertexBuffer.length;
i += 3 ) {
37199 vertex.x = vertexBuffer[
i + 0 ];
37200 vertex.y = vertexBuffer[
i + 1 ];
37201 vertex.z = vertexBuffer[
i + 2 ];
37203 const u = azimuth( vertex ) / 2 /
Math.PI + 0.5;
37204 const v = inclination( vertex ) /
Math.PI + 0.5;
37205 uvBuffer.push(
u, 1 -
v );
37215 function correctSeam() {
37219 for ( let
i = 0;
i < uvBuffer.length;
i += 6 ) {
37223 const x0 = uvBuffer[
i + 0 ];
37224 const x1 = uvBuffer[
i + 2 ];
37225 const x2 = uvBuffer[
i + 4 ];
37227 const max =
Math.max( x0, x1, x2 );
37228 const min =
Math.min( x0, x1, x2 );
37232 if (
max > 0.9 &&
min < 0.1 ) {
37234 if ( x0 < 0.2 ) uvBuffer[
i + 0 ] += 1;
37235 if ( x1 < 0.2 ) uvBuffer[
i + 2 ] += 1;
37236 if ( x2 < 0.2 ) uvBuffer[
i + 4 ] += 1;
37244 function pushVertex( vertex ) {
37246 vertexBuffer.push( vertex.x, vertex.y, vertex.z );
37250 function getVertexByIndex( index, vertex ) {
37252 const stride = index * 3;
37254 vertex.x = vertices[ stride + 0 ];
37255 vertex.y = vertices[ stride + 1 ];
37256 vertex.z = vertices[ stride + 2 ];
37260 function correctUVs() {
37266 const centroid =
new Vector3();
37272 for ( let
i = 0,
j = 0;
i < vertexBuffer.length;
i += 9,
j += 6 ) {
37274 a.set( vertexBuffer[
i + 0 ], vertexBuffer[
i + 1 ], vertexBuffer[
i + 2 ] );
37275 b.set( vertexBuffer[
i + 3 ], vertexBuffer[
i + 4 ], vertexBuffer[
i + 5 ] );
37276 c.set( vertexBuffer[
i + 6 ], vertexBuffer[
i + 7 ], vertexBuffer[
i + 8 ] );
37278 uvA.set( uvBuffer[
j + 0 ], uvBuffer[
j + 1 ] );
37279 uvB.set( uvBuffer[
j + 2 ], uvBuffer[
j + 3 ] );
37280 uvC.set( uvBuffer[
j + 4 ], uvBuffer[
j + 5 ] );
37282 centroid.copy(
a ).add(
b ).add(
c ).divideScalar( 3 );
37284 const azi = azimuth( centroid );
37286 correctUV( uvA,
j + 0,
a, azi );
37287 correctUV( uvB,
j + 2,
b, azi );
37288 correctUV( uvC,
j + 4,
c, azi );
37294 function correctUV( uv, stride, vector, azimuth ) {
37296 if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
37298 uvBuffer[ stride ] = uv.x - 1;
37302 if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
37304 uvBuffer[ stride ] = azimuth / 2 /
Math.PI + 0.5;
37312 function azimuth( vector ) {
37314 return Math.atan2( vector.z, - vector.x );
37321 function inclination( vector ) {
37323 return Math.atan2( - vector.y,
Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
37331 super.copy( source );
37333 this.parameters = Object.assign( {}, source.parameters );
37339 static fromJSON( data ) {
37341 return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details );
37349 constructor( radius = 1, detail = 0 ) {
37351 const t = ( 1 +
Math.sqrt( 5 ) ) / 2;
37357 - 1, - 1, - 1, - 1, - 1, 1,
37358 - 1, 1, - 1, - 1, 1, 1,
37359 1, - 1, - 1, 1, - 1, 1,
37360 1, 1, - 1, 1, 1, 1,
37363 0, -
r, -
t, 0, -
r,
t,
37364 0,
r, -
t, 0,
r,
t,
37367 -
r, -
t, 0, -
r,
t, 0,
37368 r, -
t, 0,
r,
t, 0,
37371 -
t, 0, -
r,
t, 0, -
r,
37376 3, 11, 7, 3, 7, 15, 3, 15, 13,
37377 7, 19, 17, 7, 17, 6, 7, 6, 15,
37378 17, 4, 8, 17, 8, 10, 17, 10, 6,
37379 8, 0, 16, 8, 16, 2, 8, 2, 10,
37380 0, 12, 1, 0, 1, 18, 0, 18, 16,
37381 6, 10, 2, 6, 2, 13, 6, 13, 15,
37382 2, 16, 18, 2, 18, 3, 2, 3, 13,
37383 18, 1, 9, 18, 9, 11, 18, 11, 3,
37384 4, 14, 12, 4, 12, 0, 4, 0, 8,
37385 11, 9, 5, 11, 5, 19, 11, 19, 7,
37386 19, 5, 14, 19, 14, 4, 19, 4, 17,
37387 1, 12, 14, 1, 14, 5, 1, 5, 9
37390 super( vertices, indices, radius, detail );
37392 this.type =
'DodecahedronGeometry';
37394 this.parameters = {
37401 static fromJSON( data ) {
37403 return new DodecahedronGeometry( data.radius, data.detail );
37411 const _normal =
new Vector3();
37416 constructor( geometry =
null, thresholdAngle = 1 ) {
37420 this.type =
'EdgesGeometry';
37422 this.parameters = {
37423 geometry: geometry,
37424 thresholdAngle: thresholdAngle
37427 if ( geometry !==
null ) {
37429 const precisionPoints = 4;
37430 const precision =
Math.pow( 10, precisionPoints );
37431 const thresholdDot =
Math.cos( DEG2RAD * thresholdAngle );
37433 const indexAttr = geometry.getIndex();
37434 const positionAttr = geometry.getAttribute(
'position' );
37435 const indexCount = indexAttr ? indexAttr.count : positionAttr.count;
37437 const indexArr = [ 0, 0, 0 ];
37438 const vertKeys = [
'a',
'b',
'c' ];
37439 const hashes =
new Array( 3 );
37441 const edgeData = {};
37442 const vertices = [];
37443 for ( let
i = 0;
i < indexCount;
i += 3 ) {
37447 indexArr[ 0 ] = indexAttr.getX(
i );
37448 indexArr[ 1 ] = indexAttr.getX(
i + 1 );
37449 indexArr[ 2 ] = indexAttr.getX(
i + 2 );
37454 indexArr[ 1 ] =
i + 1;
37455 indexArr[ 2 ] =
i + 2;
37459 const {
a,
b,
c } = _triangle;
37460 a.fromBufferAttribute( positionAttr, indexArr[ 0 ] );
37461 b.fromBufferAttribute( positionAttr, indexArr[ 1 ] );
37462 c.fromBufferAttribute( positionAttr, indexArr[ 2 ] );
37463 _triangle.getNormal( _normal );
37466 hashes[ 0 ] = `
${
Math.round(
a.x * precision ) },
${
Math.round(
a.y * precision ) },
${
Math.round(
a.z * precision ) }`;
37467 hashes[ 1 ] = `
${
Math.round(
b.x * precision ) },
${
Math.round(
b.y * precision ) },
${
Math.round(
b.z * precision ) }`;
37468 hashes[ 2 ] = `
${
Math.round(
c.x * precision ) },
${
Math.round(
c.y * precision ) },
${
Math.round(
c.z * precision ) }`;
37471 if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) {
37478 for ( let
j = 0;
j < 3;
j ++ ) {
37481 const jNext = (
j + 1 ) % 3;
37482 const vecHash0 = hashes[
j ];
37483 const vecHash1 = hashes[ jNext ];
37484 const v0 = _triangle[ vertKeys[
j ] ];
37485 const v1 = _triangle[ vertKeys[ jNext ] ];
37487 const hash = `
${ vecHash0 }_${ vecHash1 }`;
37488 const reverseHash = `
${ vecHash1 }_${ vecHash0 }`;
37490 if ( reverseHash in edgeData && edgeData[ reverseHash ] ) {
37494 if ( _normal.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) {
37496 vertices.push( v0.x, v0.y, v0.z );
37497 vertices.push(
v1.x,
v1.y,
v1.z );
37501 edgeData[ reverseHash ] =
null;
37503 }
else if ( ! ( hash in edgeData ) ) {
37506 edgeData[ hash ] = {
37508 index0: indexArr[
j ],
37509 index1: indexArr[ jNext ],
37510 normal: _normal.clone(),
37521 for (
const key in edgeData ) {
37523 if ( edgeData[ key ] ) {
37525 const { index0, index1 } = edgeData[ key ];
37526 _v0.fromBufferAttribute( positionAttr, index0 );
37527 _v1$1.fromBufferAttribute( positionAttr, index1 );
37529 vertices.push( _v0.x, _v0.y, _v0.z );
37530 vertices.push( _v1$1.x, _v1$1.y, _v1$1.z );
37536 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
37544 super.copy( source );
37546 this.parameters = Object.assign( {}, source.parameters );
37556 constructor( points ) {
37560 this.uuid = generateUUID();
37562 this.type =
'Shape';
37570 const holesPts = [];
37572 for ( let
i = 0,
l = this.holes.length;
i <
l;
i ++ ) {
37574 holesPts[
i ] = this.holes[
i ].getPoints( divisions );
37597 super.copy( source );
37601 for ( let
i = 0,
l = source.holes.length;
i <
l;
i ++ ) {
37603 const hole = source.holes[
i ];
37605 this.holes.push( hole.clone() );
37615 const data = super.toJSON();
37617 data.uuid = this.uuid;
37620 for ( let
i = 0,
l = this.holes.length;
i <
l;
i ++ ) {
37622 const hole = this.holes[
i ];
37623 data.holes.push( hole.toJSON() );
37633 super.fromJSON( json );
37635 this.uuid = json.uuid;
37638 for ( let
i = 0,
l = json.holes.length;
i <
l;
i ++ ) {
37640 const hole = json.holes[
i ];
37641 this.holes.push(
new Path().fromJSON( hole ) );
37657 triangulate:
function ( data, holeIndices, dim = 2 ) {
37659 const hasHoles = holeIndices && holeIndices.length;
37660 const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length;
37661 let outerNode = linkedList( data, 0, outerLen, dim,
true );
37662 const triangles = [];
37664 if ( ! outerNode || outerNode.next === outerNode.prev )
return triangles;
37666 let minX, minY, maxX, maxY,
x,
y, invSize;
37668 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim );
37671 if ( data.length > 80 * dim ) {
37673 minX = maxX = data[ 0 ];
37674 minY = maxY = data[ 1 ];
37676 for ( let
i = dim;
i < outerLen;
i += dim ) {
37680 if (
x < minX ) minX =
x;
37681 if (
y < minY ) minY =
y;
37682 if (
x > maxX ) maxX =
x;
37683 if (
y > maxY ) maxY =
y;
37688 invSize =
Math.max( maxX - minX, maxY - minY );
37689 invSize = invSize !== 0 ? 32767 / invSize : 0;
37693 earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 );
37702 function linkedList( data, start, end, dim, clockwise ) {
37706 if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) {
37708 for (
i = start;
i < end;
i += dim ) last = insertNode(
i, data[
i ], data[
i + 1 ], last );
37712 for (
i = end - dim;
i >= start;
i -= dim ) last = insertNode(
i, data[
i ], data[
i + 1 ], last );
37716 if ( last && equals( last, last.next ) ) {
37718 removeNode( last );
37728 function filterPoints( start, end ) {
37730 if ( ! start )
return start;
37731 if ( ! end ) end = start;
37739 if ( !
p.steiner && ( equals(
p,
p.next ) ||
area(
p.prev,
p,
p.next ) === 0 ) ) {
37743 if (
p ===
p.next )
break;
37752 }
while ( again ||
p !== end );
37759 function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) {
37761 if ( ! ear )
return;
37764 if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize );
37770 while ( ear.prev !== ear.next ) {
37775 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) {
37778 triangles.push( prev.i / dim | 0 );
37779 triangles.push( ear.i / dim | 0 );
37780 triangles.push( next.i / dim | 0 );
37795 if ( ear ===
stop ) {
37800 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 );
37804 }
else if ( pass === 1 ) {
37806 ear = cureLocalIntersections( filterPoints( ear ), triangles, dim );
37807 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 );
37811 }
else if ( pass === 2 ) {
37813 splitEarcut( ear, triangles, dim, minX, minY, invSize );
37826 function isEar( ear ) {
37828 const a = ear.prev,
37832 if (
area(
a,
b,
c ) >= 0 )
return false;
37835 const ax =
a.x, bx =
b.x, cx =
c.x, ay =
a.y, by =
b.y, cy =
c.y;
37838 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
37839 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
37840 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
37841 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
37844 while (
p !==
a ) {
37846 if (
p.x >= x0 &&
p.x <= x1 &&
p.y >= y0 &&
p.y <= y1 &&
37847 pointInTriangle( ax, ay, bx, by, cx, cy,
p.x,
p.y ) &&
37848 area(
p.prev,
p,
p.next ) >= 0 )
return false;
37857 function isEarHashed( ear, minX, minY, invSize ) {
37859 const a = ear.prev,
37863 if (
area(
a,
b,
c ) >= 0 )
return false;
37865 const ax =
a.x, bx =
b.x, cx =
c.x, ay =
a.y, by =
b.y, cy =
c.y;
37868 const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ),
37869 y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ),
37870 x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ),
37871 y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy );
37874 const minZ = zOrder( x0, y0, minX, minY, invSize ),
37875 maxZ = zOrder( x1, y1, minX, minY, invSize );
37881 while (
p &&
p.z >= minZ &&
n &&
n.z <= maxZ ) {
37883 if (
p.x >= x0 &&
p.x <= x1 &&
p.y >= y0 &&
p.y <= y1 &&
p !==
a &&
p !==
c &&
37884 pointInTriangle( ax, ay, bx, by, cx, cy,
p.x,
p.y ) &&
area(
p.prev,
p,
p.next ) >= 0 )
return false;
37887 if (
n.x >= x0 &&
n.x <= x1 &&
n.y >= y0 &&
n.y <= y1 &&
n !==
a &&
n !==
c &&
37888 pointInTriangle( ax, ay, bx, by, cx, cy,
n.x,
n.y ) &&
area(
n.prev,
n,
n.next ) >= 0 )
return false;
37894 while (
p &&
p.z >= minZ ) {
37896 if (
p.x >= x0 &&
p.x <= x1 &&
p.y >= y0 &&
p.y <= y1 &&
p !==
a &&
p !==
c &&
37897 pointInTriangle( ax, ay, bx, by, cx, cy,
p.x,
p.y ) &&
area(
p.prev,
p,
p.next ) >= 0 )
return false;
37903 while (
n &&
n.z <= maxZ ) {
37905 if (
n.x >= x0 &&
n.x <= x1 &&
n.y >= y0 &&
n.y <= y1 &&
n !==
a &&
n !==
c &&
37906 pointInTriangle( ax, ay, bx, by, cx, cy,
n.x,
n.y ) &&
area(
n.prev,
n,
n.next ) >= 0 )
return false;
37916 function cureLocalIntersections( start, triangles, dim ) {
37924 if ( ! equals(
a,
b ) && intersects(
a,
p,
p.next,
b ) && locallyInside(
a,
b ) && locallyInside(
b,
a ) ) {
37926 triangles.push(
a.i / dim | 0 );
37927 triangles.push(
p.i / dim | 0 );
37928 triangles.push(
b.i / dim | 0 );
37932 removeNode(
p.next );
37940 }
while (
p !== start );
37942 return filterPoints(
p );
37947 function splitEarcut( start, triangles, dim, minX, minY, invSize ) {
37953 let
b =
a.next.next;
37954 while (
b !==
a.prev ) {
37956 if (
a.i !==
b.i && isValidDiagonal(
a,
b ) ) {
37959 let
c = splitPolygon(
a,
b );
37962 a = filterPoints(
a,
a.next );
37963 c = filterPoints(
c,
c.next );
37966 earcutLinked(
a, triangles, dim, minX, minY, invSize, 0 );
37967 earcutLinked(
c, triangles, dim, minX, minY, invSize, 0 );
37978 }
while (
a !== start );
37983 function eliminateHoles( data, holeIndices, outerNode, dim ) {
37986 let
i, len, start, end, list;
37988 for (
i = 0, len = holeIndices.length;
i < len;
i ++ ) {
37990 start = holeIndices[
i ] * dim;
37991 end =
i < len - 1 ? holeIndices[
i + 1 ] * dim : data.length;
37992 list = linkedList( data, start, end, dim,
false );
37993 if ( list === list.next ) list.steiner =
true;
37994 queue.push( getLeftmost( list ) );
37998 queue.sort( compareX );
38001 for (
i = 0;
i < queue.length;
i ++ ) {
38003 outerNode = eliminateHole( queue[
i ], outerNode );
38011 function compareX(
a,
b ) {
38018 function eliminateHole( hole, outerNode ) {
38020 const bridge = findHoleBridge( hole, outerNode );
38027 const bridgeReverse = splitPolygon( bridge, hole );
38030 filterPoints( bridgeReverse, bridgeReverse.next );
38031 return filterPoints( bridge, bridge.next );
38036 function findHoleBridge( hole, outerNode ) {
38042 const hx = hole.x, hy = hole.y;
38048 if ( hy <= p.y && hy >=
p.next.y &&
p.next.y !==
p.y ) {
38050 const x =
p.x + ( hy -
p.y ) * (
p.next.x -
p.x ) / (
p.next.y -
p.y );
38054 m =
p.x <
p.next.x ?
p :
p.next;
38055 if (
x === hx )
return m;
38063 }
while (
p !== outerNode );
38065 if ( !
m )
return null;
38074 let tanMin = Infinity, tan;
38080 if ( hx >=
p.x &&
p.x >= mx && hx !==
p.x &&
38081 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy,
p.x,
p.y ) ) {
38083 tan =
Math.abs( hy -
p.y ) / ( hx -
p.x );
38085 if ( locallyInside(
p, hole ) && ( tan < tanMin || ( tan === tanMin && (
p.x >
m.x || (
p.x ===
m.x && sectorContainsSector(
m,
p ) ) ) ) ) ) {
38096 }
while (
p !==
stop );
38103 function sectorContainsSector(
m,
p ) {
38105 return area(
m.prev,
m,
p.prev ) < 0 &&
area(
p.next,
m,
m.next ) < 0;
38110 function indexCurve( start, minX, minY, invSize ) {
38115 if (
p.z === 0 )
p.z = zOrder(
p.x,
p.y, minX, minY, invSize );
38120 }
while (
p !== start );
38122 p.prevZ.nextZ =
null;
38131 function sortLinked( list ) {
38133 let
i,
p,
q,
e, tail, numMerges, pSize, qSize,
38148 for (
i = 0;
i < inSize;
i ++ ) {
38158 while ( pSize > 0 || ( qSize > 0 &&
q ) ) {
38160 if ( pSize !== 0 && ( qSize === 0 || !
q ||
p.z <=
q.z ) ) {
38174 if ( tail ) tail.nextZ =
e;
38189 }
while ( numMerges > 1 );
38196 function zOrder(
x,
y, minX, minY, invSize ) {
38199 x = (
x - minX ) * invSize | 0;
38200 y = (
y - minY ) * invSize | 0;
38202 x = (
x | (
x << 8 ) ) & 0x00FF00FF;
38203 x = (
x | (
x << 4 ) ) & 0x0F0F0F0F;
38204 x = (
x | (
x << 2 ) ) & 0x33333333;
38205 x = (
x | (
x << 1 ) ) & 0x55555555;
38207 y = (
y | (
y << 8 ) ) & 0x00FF00FF;
38208 y = (
y | (
y << 4 ) ) & 0x0F0F0F0F;
38209 y = (
y | (
y << 2 ) ) & 0x33333333;
38210 y = (
y | (
y << 1 ) ) & 0x55555555;
38212 return x | (
y << 1 );
38217 function getLeftmost( start ) {
38223 if (
p.x < leftmost.x || (
p.x === leftmost.x &&
p.y < leftmost.y ) ) leftmost =
p;
38226 }
while (
p !== start );
38233 function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) {
38235 return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) &&
38236 ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) &&
38237 ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py );
38242 function isValidDiagonal(
a,
b ) {
38244 return a.next.i !==
b.i &&
a.prev.i !==
b.i && ! intersectsPolygon(
a,
b ) &&
38245 ( locallyInside(
a,
b ) && locallyInside(
b,
a ) && middleInside(
a,
b ) &&
38247 equals(
a,
b ) &&
area(
a.prev,
a,
a.next ) > 0 &&
area(
b.prev,
b,
b.next ) > 0 );
38254 return (
q.y -
p.y ) * (
r.x -
q.x ) - (
q.x -
p.x ) * (
r.y -
q.y );
38259 function equals( p1, p2 ) {
38261 return p1.x === p2.x && p1.y === p2.y;
38266 function intersects( p1, q1, p2, q2 ) {
38268 const o1 = sign(
area( p1, q1, p2 ) );
38269 const o2 = sign(
area( p1, q1, q2 ) );
38270 const o3 = sign(
area( p2, q2, p1 ) );
38271 const o4 = sign(
area( p2, q2, q1 ) );
38273 if ( o1 !== o2 && o3 !== o4 )
return true;
38275 if ( o1 === 0 && onSegment( p1, p2, q1 ) )
return true;
38276 if ( o2 === 0 && onSegment( p1, q2, q1 ) )
return true;
38277 if ( o3 === 0 && onSegment( p2, p1, q2 ) )
return true;
38278 if ( o4 === 0 && onSegment( p2, q1, q2 ) )
return true;
38285 function onSegment(
p,
q,
r ) {
38291 function sign( num ) {
38293 return num > 0 ? 1 : num < 0 ? - 1 : 0;
38298 function intersectsPolygon(
a,
b ) {
38303 if (
p.i !==
a.i &&
p.next.i !==
a.i &&
p.i !==
b.i &&
p.next.i !==
b.i &&
38304 intersects(
p,
p.next,
a,
b ) )
return true;
38307 }
while (
p !==
a );
38314 function locallyInside(
a,
b ) {
38316 return area(
a.prev,
a,
a.next ) < 0 ?
38323 function middleInside(
a,
b ) {
38327 const px = (
a.x +
b.x ) / 2,
38328 py = (
a.y +
b.y ) / 2;
38331 if ( ( (
p.y > py ) !== (
p.next.y > py ) ) &&
p.next.y !==
p.y &&
38332 ( px < (
p.next.x -
p.x ) * ( py -
p.y ) / (
p.next.y -
p.y ) +
p.x ) )
38336 }
while (
p !==
a );
38344 function splitPolygon(
a,
b ) {
38346 const a2 =
new Node(
a.i,
a.x,
a.y ),
38347 b2 =
new Node(
b.i,
b.x,
b.y ),
38368 function insertNode(
i,
x,
y, last ) {
38370 const p =
new Node(
i,
x,
y );
38379 p.next = last.next;
38381 last.next.prev =
p;
38390 function removeNode(
p ) {
38392 p.next.prev =
p.prev;
38393 p.prev.next =
p.next;
38395 if (
p.prevZ )
p.prevZ.nextZ =
p.nextZ;
38396 if (
p.nextZ )
p.nextZ.prevZ =
p.prevZ;
38400 function Node(
i,
x,
y ) {
38421 this.steiner =
false;
38425 function signedArea( data, start, end, dim ) {
38428 for ( let
i = start,
j = end - dim;
i < end;
i += dim ) {
38430 sum += ( data[
j ] - data[
i ] ) * ( data[
i + 1 ] + data[
j + 1 ] );
38443 static area( contour ) {
38445 const n = contour.length;
38448 for ( let
p =
n - 1,
q = 0;
q <
n;
p =
q ++ ) {
38450 a += contour[
p ].x * contour[
q ].y - contour[
q ].x * contour[
p ].y;
38458 static isClockWise( pts ) {
38460 return ShapeUtils.area( pts ) < 0;
38464 static triangulateShape( contour, holes ) {
38466 const vertices = [];
38467 const holeIndices = [];
38470 removeDupEndPts( contour );
38471 addContour( vertices, contour );
38475 let holeIndex = contour.length;
38477 holes.forEach( removeDupEndPts );
38479 for ( let
i = 0;
i < holes.length;
i ++ ) {
38481 holeIndices.push( holeIndex );
38482 holeIndex += holes[
i ].length;
38483 addContour( vertices, holes[
i ] );
38489 const triangles = Earcut.triangulate( vertices, holeIndices );
38493 for ( let
i = 0;
i < triangles.length;
i += 3 ) {
38495 faces.push( triangles.slice(
i,
i + 3 ) );
38505 function removeDupEndPts( points ) {
38507 const l = points.length;
38509 if (
l > 2 && points[
l - 1 ].equals( points[ 0 ] ) ) {
38517 function addContour( vertices, contour ) {
38519 for ( let
i = 0;
i < contour.length;
i ++ ) {
38521 vertices.push( contour[
i ].
x );
38522 vertices.push( contour[
i ].
y );
38553 constructor( shapes =
new Shape( [
new Vector2( 0.5, 0.5 ),
new Vector2( - 0.5, 0.5 ),
new Vector2( - 0.5, - 0.5 ),
new Vector2( 0.5, - 0.5 ) ] ), options = {} ) {
38557 this.type =
'ExtrudeGeometry';
38559 this.parameters = {
38564 shapes =
Array.isArray( shapes ) ? shapes : [ shapes ];
38566 const scope =
this;
38568 const verticesArray = [];
38569 const uvArray = [];
38571 for ( let
i = 0,
l = shapes.length;
i <
l;
i ++ ) {
38573 const shape = shapes[
i ];
38580 this.setAttribute(
'position',
new Float32BufferAttribute( verticesArray, 3 ) );
38581 this.setAttribute(
'uv',
new Float32BufferAttribute( uvArray, 2 ) );
38583 this.computeVertexNormals();
38589 const placeholder = [];
38593 const curveSegments = options.curveSegments !==
undefined ? options.curveSegments : 12;
38594 const steps = options.steps !==
undefined ? options.steps : 1;
38595 const depth = options.depth !==
undefined ? options.depth : 1;
38597 let bevelEnabled = options.bevelEnabled !==
undefined ? options.bevelEnabled :
true;
38598 let bevelThickness = options.bevelThickness !==
undefined ? options.bevelThickness : 0.2;
38599 let bevelSize = options.bevelSize !==
undefined ? options.bevelSize : bevelThickness - 0.1;
38600 let bevelOffset = options.bevelOffset !==
undefined ? options.bevelOffset : 0;
38601 let bevelSegments = options.bevelSegments !==
undefined ? options.bevelSegments : 3;
38603 const extrudePath = options.extrudePath;
38609 let extrudePts, extrudeByPath =
false;
38610 let splineTube, binormal,
normal, position2;
38612 if ( extrudePath ) {
38614 extrudePts = extrudePath.getSpacedPoints( steps );
38616 extrudeByPath =
true;
38617 bevelEnabled =
false;
38623 splineTube = extrudePath.computeFrenetFrames( steps,
false );
38635 if ( ! bevelEnabled ) {
38638 bevelThickness = 0;
38646 const shapePoints = shape.extractPoints( curveSegments );
38648 let vertices = shapePoints.shape;
38649 const holes = shapePoints.holes;
38651 const reverse = ! ShapeUtils.isClockWise( vertices );
38655 vertices = vertices.reverse();
38659 for ( let
h = 0, hl = holes.length;
h < hl;
h ++ ) {
38661 const ahole = holes[
h ];
38663 if ( ShapeUtils.isClockWise( ahole ) ) {
38665 holes[
h ] = ahole.reverse();
38674 const faces = ShapeUtils.triangulateShape( vertices, holes );
38678 const contour = vertices;
38680 for ( let
h = 0, hl = holes.length;
h < hl;
h ++ ) {
38682 const ahole = holes[
h ];
38684 vertices = vertices.concat( ahole );
38689 function scalePt2(
pt, vec, size ) {
38691 if ( ! vec ) console.error(
'THREE.ExtrudeGeometry: vec does not exist' );
38693 return pt.clone().addScaledVector( vec, size );
38697 const vlen = vertices.length, flen = faces.length;
38703 function getBevelVec( inPt, inPrev, inNext ) {
38712 let v_trans_x, v_trans_y, shrink_by;
38717 const v_prev_x = inPt.x - inPrev.x,
38718 v_prev_y = inPt.y - inPrev.y;
38719 const v_next_x = inNext.x - inPt.x,
38720 v_next_y = inNext.y - inPt.y;
38722 const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y );
38725 const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x );
38727 if (
Math.abs( collinear0 ) >
Number.EPSILON ) {
38733 const v_prev_len =
Math.sqrt( v_prev_lensq );
38734 const v_next_len =
Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y );
38738 const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len );
38739 const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len );
38741 const ptNextShift_x = ( inNext.x - v_next_y / v_next_len );
38742 const ptNextShift_y = ( inNext.y + v_next_x / v_next_len );
38746 const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y -
38747 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) /
38748 ( v_prev_x * v_next_y - v_prev_y * v_next_x );
38752 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x );
38753 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y );
38757 const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y );
38758 if ( v_trans_lensq <= 2 ) {
38760 return new Vector2( v_trans_x, v_trans_y );
38764 shrink_by =
Math.sqrt( v_trans_lensq / 2 );
38772 let direction_eq =
false;
38774 if ( v_prev_x >
Number.EPSILON ) {
38776 if ( v_next_x >
Number.EPSILON ) {
38778 direction_eq =
true;
38784 if ( v_prev_x < -
Number.EPSILON ) {
38786 if ( v_next_x < -
Number.EPSILON ) {
38788 direction_eq =
true;
38794 if (
Math.sign( v_prev_y ) ===
Math.sign( v_next_y ) ) {
38796 direction_eq =
true;
38804 if ( direction_eq ) {
38807 v_trans_x = - v_prev_y;
38808 v_trans_y = v_prev_x;
38809 shrink_by =
Math.sqrt( v_prev_lensq );
38814 v_trans_x = v_prev_x;
38815 v_trans_y = v_prev_y;
38816 shrink_by =
Math.sqrt( v_prev_lensq / 2 );
38822 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by );
38827 const contourMovements = [];
38829 for ( let
i = 0, il = contour.length,
j = il - 1,
k =
i + 1;
i < il;
i ++,
j ++,
k ++ ) {
38831 if (
j === il )
j = 0;
38832 if (
k === il )
k = 0;
38837 contourMovements[
i ] = getBevelVec( contour[
i ], contour[
j ], contour[
k ] );
38841 const holesMovements = [];
38842 let oneHoleMovements, verticesMovements = contourMovements.concat();
38844 for ( let
h = 0, hl = holes.length;
h < hl;
h ++ ) {
38846 const ahole = holes[
h ];
38848 oneHoleMovements = [];
38850 for ( let
i = 0, il = ahole.length,
j = il - 1,
k =
i + 1;
i < il;
i ++,
j ++,
k ++ ) {
38852 if (
j === il )
j = 0;
38853 if (
k === il )
k = 0;
38856 oneHoleMovements[
i ] = getBevelVec( ahole[
i ], ahole[
j ], ahole[
k ] );
38860 holesMovements.push( oneHoleMovements );
38861 verticesMovements = verticesMovements.concat( oneHoleMovements );
38868 for ( let
b = 0;
b < bevelSegments;
b ++ ) {
38872 const t =
b / bevelSegments;
38873 const z = bevelThickness *
Math.cos(
t *
Math.PI / 2 );
38874 const bs = bevelSize *
Math.sin(
t *
Math.PI / 2 ) + bevelOffset;
38878 for ( let
i = 0, il = contour.length;
i < il;
i ++ ) {
38880 const vert = scalePt2( contour[
i ], contourMovements[
i ], bs );
38882 v( vert.x, vert.y, -
z );
38888 for ( let
h = 0, hl = holes.length;
h < hl;
h ++ ) {
38890 const ahole = holes[
h ];
38891 oneHoleMovements = holesMovements[
h ];
38893 for ( let
i = 0, il = ahole.length;
i < il;
i ++ ) {
38895 const vert = scalePt2( ahole[
i ], oneHoleMovements[
i ], bs );
38897 v( vert.x, vert.y, -
z );
38905 const bs = bevelSize + bevelOffset;
38909 for ( let
i = 0;
i < vlen;
i ++ ) {
38911 const vert = bevelEnabled ? scalePt2( vertices[
i ], verticesMovements[
i ], bs ) : vertices[
i ];
38913 if ( ! extrudeByPath ) {
38915 v( vert.x, vert.y, 0 );
38921 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x );
38922 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y );
38924 position2.copy( extrudePts[ 0 ] ).add(
normal ).add( binormal );
38926 v( position2.x, position2.y, position2.z );
38935 for ( let
s = 1;
s <= steps;
s ++ ) {
38937 for ( let
i = 0;
i < vlen;
i ++ ) {
38939 const vert = bevelEnabled ? scalePt2( vertices[
i ], verticesMovements[
i ], bs ) : vertices[
i ];
38941 if ( ! extrudeByPath ) {
38943 v( vert.x, vert.y, depth / steps *
s );
38949 normal.copy( splineTube.normals[
s ] ).multiplyScalar( vert.x );
38950 binormal.copy( splineTube.binormals[
s ] ).multiplyScalar( vert.y );
38952 position2.copy( extrudePts[
s ] ).add(
normal ).add( binormal );
38954 v( position2.x, position2.y, position2.z );
38966 for ( let
b = bevelSegments - 1;
b >= 0;
b -- ) {
38968 const t =
b / bevelSegments;
38969 const z = bevelThickness *
Math.cos(
t *
Math.PI / 2 );
38970 const bs = bevelSize *
Math.sin(
t *
Math.PI / 2 ) + bevelOffset;
38974 for ( let
i = 0, il = contour.length;
i < il;
i ++ ) {
38976 const vert = scalePt2( contour[
i ], contourMovements[
i ], bs );
38977 v( vert.x, vert.y, depth +
z );
38983 for ( let
h = 0, hl = holes.length;
h < hl;
h ++ ) {
38985 const ahole = holes[
h ];
38986 oneHoleMovements = holesMovements[
h ];
38988 for ( let
i = 0, il = ahole.length;
i < il;
i ++ ) {
38990 const vert = scalePt2( ahole[
i ], oneHoleMovements[
i ], bs );
38992 if ( ! extrudeByPath ) {
38994 v( vert.x, vert.y, depth +
z );
38998 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x +
z );
39021 function buildLidFaces() {
39023 const start = verticesArray.length / 3;
39025 if ( bevelEnabled ) {
39028 let offset = vlen * layer;
39032 for ( let
i = 0;
i < flen;
i ++ ) {
39034 const face = faces[
i ];
39035 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset );
39039 layer = steps + bevelSegments * 2;
39040 offset = vlen * layer;
39044 for ( let
i = 0;
i < flen;
i ++ ) {
39046 const face = faces[
i ];
39047 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset );
39055 for ( let
i = 0;
i < flen;
i ++ ) {
39057 const face = faces[
i ];
39058 f3( face[ 2 ], face[ 1 ], face[ 0 ] );
39064 for ( let
i = 0;
i < flen;
i ++ ) {
39066 const face = faces[
i ];
39067 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps );
39073 scope.addGroup( start, verticesArray.length / 3 - start, 0 );
39079 function buildSideFaces() {
39081 const start = verticesArray.length / 3;
39082 let layeroffset = 0;
39083 sidewalls( contour, layeroffset );
39084 layeroffset += contour.length;
39086 for ( let
h = 0, hl = holes.length;
h < hl;
h ++ ) {
39088 const ahole = holes[
h ];
39089 sidewalls( ahole, layeroffset );
39092 layeroffset += ahole.length;
39097 scope.addGroup( start, verticesArray.length / 3 - start, 1 );
39102 function sidewalls( contour, layeroffset ) {
39104 let
i = contour.length;
39106 while ( --
i >= 0 ) {
39110 if (
k < 0 )
k = contour.length - 1;
39114 for ( let
s = 0, sl = ( steps + bevelSegments * 2 );
s < sl;
s ++ ) {
39116 const slen1 = vlen *
s;
39117 const slen2 = vlen * (
s + 1 );
39119 const a = layeroffset +
j + slen1,
39120 b = layeroffset +
k + slen1,
39121 c = layeroffset +
k + slen2,
39122 d = layeroffset +
j + slen2;
39132 function v(
x,
y,
z ) {
39134 placeholder.push(
x );
39135 placeholder.push(
y );
39136 placeholder.push(
z );
39141 function f3(
a,
b,
c ) {
39147 const nextIndex = verticesArray.length / 3;
39148 const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
39156 function f4(
a,
b,
c,
d ) {
39167 const nextIndex = verticesArray.length / 3;
39168 const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 );
39180 function addVertex( index ) {
39182 verticesArray.push( placeholder[ index * 3 + 0 ] );
39183 verticesArray.push( placeholder[ index * 3 + 1 ] );
39184 verticesArray.push( placeholder[ index * 3 + 2 ] );
39189 function addUV( vector2 ) {
39191 uvArray.push( vector2.x );
39192 uvArray.push( vector2.y );
39202 super.copy( source );
39204 this.parameters = Object.assign( {}, source.parameters );
39212 const data = super.toJSON();
39214 const shapes = this.parameters.shapes;
39215 const options = this.parameters.options;
39217 return toJSON$1( shapes, options, data );
39221 static fromJSON( data, shapes ) {
39223 const geometryShapes = [];
39225 for ( let
j = 0, jl = data.shapes.length;
j < jl;
j ++ ) {
39227 const shape = shapes[ data.shapes[
j ] ];
39229 geometryShapes.push( shape );
39233 const extrudePath = data.options.extrudePath;
39237 data.options.extrudePath =
new Curves[ extrudePath.type ]().fromJSON( extrudePath );
39249 generateTopUV:
function ( geometry, vertices, indexA, indexB, indexC ) {
39251 const a_x = vertices[ indexA * 3 ];
39252 const a_y = vertices[ indexA * 3 + 1 ];
39253 const b_x = vertices[ indexB * 3 ];
39254 const b_y = vertices[ indexB * 3 + 1 ];
39255 const c_x = vertices[ indexC * 3 ];
39256 const c_y = vertices[ indexC * 3 + 1 ];
39266 generateSideWallUV:
function ( geometry, vertices, indexA, indexB, indexC, indexD ) {
39268 const a_x = vertices[ indexA * 3 ];
39269 const a_y = vertices[ indexA * 3 + 1 ];
39270 const a_z = vertices[ indexA * 3 + 2 ];
39271 const b_x = vertices[ indexB * 3 ];
39272 const b_y = vertices[ indexB * 3 + 1 ];
39273 const b_z = vertices[ indexB * 3 + 2 ];
39274 const c_x = vertices[ indexC * 3 ];
39275 const c_y = vertices[ indexC * 3 + 1 ];
39276 const c_z = vertices[ indexC * 3 + 2 ];
39277 const d_x = vertices[ indexD * 3 ];
39278 const d_y = vertices[ indexD * 3 + 1 ];
39279 const d_z = vertices[ indexD * 3 + 2 ];
39281 if (
Math.abs( a_y - b_y ) <
Math.abs( a_x - b_x ) ) {
39305 function toJSON$1( shapes, options, data ) {
39309 if (
Array.isArray( shapes ) ) {
39311 for ( let
i = 0,
l = shapes.length;
i <
l;
i ++ ) {
39313 const shape = shapes[
i ];
39315 data.shapes.push( shape.uuid );
39321 data.shapes.push( shapes.uuid );
39325 data.options = Object.assign( {}, options );
39327 if ( options.extrudePath !==
undefined ) data.options.extrudePath = options.extrudePath.toJSON();
39335 constructor( radius = 1, detail = 0 ) {
39337 const t = ( 1 +
Math.sqrt( 5 ) ) / 2;
39340 - 1,
t, 0, 1,
t, 0, - 1, -
t, 0, 1, -
t, 0,
39341 0, - 1,
t, 0, 1,
t, 0, - 1, -
t, 0, 1, -
t,
39342 t, 0, - 1,
t, 0, 1, -
t, 0, - 1, -
t, 0, 1
39346 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11,
39347 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8,
39348 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9,
39349 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1
39352 super( vertices, indices, radius, detail );
39354 this.type =
'IcosahedronGeometry';
39356 this.parameters = {
39363 static fromJSON( data ) {
39373 constructor( radius = 1, detail = 0 ) {
39376 1, 0, 0, - 1, 0, 0, 0, 1, 0,
39377 0, - 1, 0, 0, 0, 1, 0, 0, - 1
39381 0, 2, 4, 0, 4, 3, 0, 3, 5,
39382 0, 5, 2, 1, 2, 5, 1, 5, 3,
39386 super( vertices, indices, radius, detail );
39388 this.type =
'OctahedronGeometry';
39390 this.parameters = {
39397 static fromJSON( data ) {
39407 constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength =
Math.PI * 2 ) {
39411 this.type =
'RingGeometry';
39413 this.parameters = {
39414 innerRadius: innerRadius,
39415 outerRadius: outerRadius,
39416 thetaSegments: thetaSegments,
39417 phiSegments: phiSegments,
39418 thetaStart: thetaStart,
39419 thetaLength: thetaLength
39422 thetaSegments =
Math.max( 3, thetaSegments );
39423 phiSegments =
Math.max( 1, phiSegments );
39427 const indices = [];
39428 const vertices = [];
39429 const normals = [];
39434 let radius = innerRadius;
39435 const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments );
39436 const vertex =
new Vector3();
39441 for ( let
j = 0;
j <= phiSegments;
j ++ ) {
39443 for ( let
i = 0;
i <= thetaSegments;
i ++ ) {
39447 const segment = thetaStart +
i / thetaSegments * thetaLength;
39451 vertex.x = radius *
Math.cos( segment );
39452 vertex.y = radius *
Math.sin( segment );
39454 vertices.push( vertex.x, vertex.y, vertex.z );
39458 normals.push( 0, 0, 1 );
39462 uv.x = ( vertex.x / outerRadius + 1 ) / 2;
39463 uv.y = ( vertex.y / outerRadius + 1 ) / 2;
39465 uvs.push( uv.x, uv.y );
39471 radius += radiusStep;
39477 for ( let
j = 0;
j < phiSegments;
j ++ ) {
39479 const thetaSegmentLevel =
j * ( thetaSegments + 1 );
39481 for ( let
i = 0;
i < thetaSegments;
i ++ ) {
39483 const segment =
i + thetaSegmentLevel;
39486 const b = segment + thetaSegments + 1;
39487 const c = segment + thetaSegments + 2;
39488 const d = segment + 1;
39492 indices.push(
a,
b,
d );
39493 indices.push(
b,
c,
d );
39501 this.setIndex( indices );
39502 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
39503 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
39504 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
39510 super.copy( source );
39512 this.parameters = Object.assign( {}, source.parameters );
39518 static fromJSON( data ) {
39520 return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength );
39528 constructor( shapes =
new Shape( [
new Vector2( 0, 0.5 ),
new Vector2( - 0.5, - 0.5 ),
new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) {
39532 this.type =
'ShapeGeometry';
39534 this.parameters = {
39536 curveSegments: curveSegments
39541 const indices = [];
39542 const vertices = [];
39543 const normals = [];
39548 let groupStart = 0;
39549 let groupCount = 0;
39553 if (
Array.isArray( shapes ) ===
false ) {
39559 for ( let
i = 0;
i < shapes.length;
i ++ ) {
39563 this.addGroup( groupStart, groupCount,
i );
39565 groupStart += groupCount;
39574 this.setIndex( indices );
39575 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
39576 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
39577 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
39584 const indexOffset = vertices.length / 3;
39585 const points = shape.extractPoints( curveSegments );
39587 let shapeVertices = points.shape;
39588 const shapeHoles = points.holes;
39592 if ( ShapeUtils.isClockWise( shapeVertices ) ===
false ) {
39594 shapeVertices = shapeVertices.reverse();
39598 for ( let
i = 0,
l = shapeHoles.length;
i <
l;
i ++ ) {
39600 const shapeHole = shapeHoles[
i ];
39602 if ( ShapeUtils.isClockWise( shapeHole ) ===
true ) {
39604 shapeHoles[
i ] = shapeHole.reverse();
39610 const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles );
39614 for ( let
i = 0,
l = shapeHoles.length;
i <
l;
i ++ ) {
39616 const shapeHole = shapeHoles[
i ];
39617 shapeVertices = shapeVertices.concat( shapeHole );
39623 for ( let
i = 0,
l = shapeVertices.length;
i <
l;
i ++ ) {
39625 const vertex = shapeVertices[
i ];
39627 vertices.push( vertex.x, vertex.y, 0 );
39628 normals.push( 0, 0, 1 );
39629 uvs.push( vertex.x, vertex.y );
39635 for ( let
i = 0,
l = faces.length;
i <
l;
i ++ ) {
39637 const face = faces[
i ];
39639 const a = face[ 0 ] + indexOffset;
39640 const b = face[ 1 ] + indexOffset;
39641 const c = face[ 2 ] + indexOffset;
39643 indices.push(
a,
b,
c );
39654 super.copy( source );
39656 this.parameters = Object.assign( {}, source.parameters );
39664 const data = super.toJSON();
39666 const shapes = this.parameters.shapes;
39668 return toJSON( shapes, data );
39672 static fromJSON( data, shapes ) {
39674 const geometryShapes = [];
39676 for ( let
j = 0, jl = data.shapes.length;
j < jl;
j ++ ) {
39678 const shape = shapes[ data.shapes[
j ] ];
39680 geometryShapes.push( shape );
39684 return new ShapeGeometry( geometryShapes, data.curveSegments );
39690 function toJSON( shapes, data ) {
39694 if (
Array.isArray( shapes ) ) {
39696 for ( let
i = 0,
l = shapes.length;
i <
l;
i ++ ) {
39698 const shape = shapes[
i ];
39700 data.shapes.push( shape.uuid );
39706 data.shapes.push( shapes.uuid );
39716 constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength =
Math.PI * 2, thetaStart = 0, thetaLength =
Math.PI ) {
39720 this.type =
'SphereGeometry';
39722 this.parameters = {
39724 widthSegments: widthSegments,
39725 heightSegments: heightSegments,
39726 phiStart: phiStart,
39727 phiLength: phiLength,
39728 thetaStart: thetaStart,
39729 thetaLength: thetaLength
39732 widthSegments =
Math.max( 3,
Math.floor( widthSegments ) );
39733 heightSegments =
Math.max( 2,
Math.floor( heightSegments ) );
39735 const thetaEnd =
Math.min( thetaStart + thetaLength,
Math.PI );
39740 const vertex =
new Vector3();
39745 const indices = [];
39746 const vertices = [];
39747 const normals = [];
39752 for ( let iy = 0; iy <= heightSegments; iy ++ ) {
39754 const verticesRow = [];
39756 const v = iy / heightSegments;
39762 if ( iy === 0 && thetaStart === 0 ) {
39764 uOffset = 0.5 / widthSegments;
39766 }
else if ( iy === heightSegments && thetaEnd ===
Math.PI ) {
39768 uOffset = - 0.5 / widthSegments;
39772 for ( let ix = 0; ix <= widthSegments; ix ++ ) {
39774 const u = ix / widthSegments;
39778 vertex.x = - radius *
Math.cos( phiStart +
u * phiLength ) *
Math.sin( thetaStart +
v * thetaLength );
39779 vertex.y = radius *
Math.cos( thetaStart +
v * thetaLength );
39780 vertex.z = radius *
Math.sin( phiStart +
u * phiLength ) *
Math.sin( thetaStart +
v * thetaLength );
39782 vertices.push( vertex.x, vertex.y, vertex.z );
39786 normal.copy( vertex ).normalize();
39791 uvs.push(
u + uOffset, 1 -
v );
39793 verticesRow.push( index ++ );
39797 grid.push( verticesRow );
39803 for ( let iy = 0; iy < heightSegments; iy ++ ) {
39805 for ( let ix = 0; ix < widthSegments; ix ++ ) {
39807 const a = grid[ iy ][ ix + 1 ];
39808 const b = grid[ iy ][ ix ];
39809 const c = grid[ iy + 1 ][ ix ];
39810 const d = grid[ iy + 1 ][ ix + 1 ];
39812 if ( iy !== 0 || thetaStart > 0 ) indices.push(
a,
b,
d );
39813 if ( iy !== heightSegments - 1 || thetaEnd <
Math.PI ) indices.push(
b,
c,
d );
39821 this.setIndex( indices );
39822 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
39823 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
39824 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
39830 super.copy( source );
39832 this.parameters = Object.assign( {}, source.parameters );
39838 static fromJSON( data ) {
39840 return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength );
39848 constructor( radius = 1, detail = 0 ) {
39851 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1
39855 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1
39858 super( vertices, indices, radius, detail );
39860 this.type =
'TetrahedronGeometry';
39862 this.parameters = {
39869 static fromJSON( data ) {
39879 constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48,
arc =
Math.PI * 2 ) {
39883 this.type =
'TorusGeometry';
39885 this.parameters = {
39888 radialSegments: radialSegments,
39889 tubularSegments: tubularSegments,
39893 radialSegments =
Math.floor( radialSegments );
39894 tubularSegments =
Math.floor( tubularSegments );
39898 const indices = [];
39899 const vertices = [];
39900 const normals = [];
39905 const center =
new Vector3();
39906 const vertex =
new Vector3();
39911 for ( let
j = 0;
j <= radialSegments;
j ++ ) {
39913 for ( let
i = 0;
i <= tubularSegments;
i ++ ) {
39915 const u =
i / tubularSegments *
arc;
39916 const v =
j / radialSegments *
Math.PI * 2;
39920 vertex.x = ( radius + tube *
Math.cos(
v ) ) *
Math.cos(
u );
39921 vertex.y = ( radius + tube *
Math.cos(
v ) ) *
Math.sin(
u );
39922 vertex.z = tube *
Math.sin(
v );
39924 vertices.push( vertex.x, vertex.y, vertex.z );
39928 center.x = radius *
Math.cos(
u );
39929 center.y = radius *
Math.sin(
u );
39930 normal.subVectors( vertex, center ).normalize();
39936 uvs.push(
i / tubularSegments );
39937 uvs.push(
j / radialSegments );
39945 for ( let
j = 1;
j <= radialSegments;
j ++ ) {
39947 for ( let
i = 1;
i <= tubularSegments;
i ++ ) {
39951 const a = ( tubularSegments + 1 ) *
j +
i - 1;
39952 const b = ( tubularSegments + 1 ) * (
j - 1 ) +
i - 1;
39953 const c = ( tubularSegments + 1 ) * (
j - 1 ) +
i;
39954 const d = ( tubularSegments + 1 ) *
j +
i;
39958 indices.push(
a,
b,
d );
39959 indices.push(
b,
c,
d );
39967 this.setIndex( indices );
39968 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
39969 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
39970 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
39976 super.copy( source );
39978 this.parameters = Object.assign( {}, source.parameters );
39984 static fromJSON( data ) {
39986 return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc );
39994 constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8,
p = 2,
q = 3 ) {
39998 this.type =
'TorusKnotGeometry';
40000 this.parameters = {
40003 tubularSegments: tubularSegments,
40004 radialSegments: radialSegments,
40009 tubularSegments =
Math.floor( tubularSegments );
40010 radialSegments =
Math.floor( radialSegments );
40014 const indices = [];
40015 const vertices = [];
40016 const normals = [];
40021 const vertex =
new Vector3();
40033 for ( let
i = 0;
i <= tubularSegments; ++
i ) {
40037 const u =
i / tubularSegments *
p *
Math.PI * 2;
40042 calculatePositionOnCurve(
u,
p,
q, radius, P1 );
40043 calculatePositionOnCurve(
u + 0.01,
p,
q, radius, P2 );
40047 T.subVectors( P2, P1 );
40048 N.addVectors( P2, P1 );
40049 B.crossVectors(
T,
N );
40050 N.crossVectors(
B,
T );
40057 for ( let
j = 0;
j <= radialSegments; ++
j ) {
40062 const v =
j / radialSegments *
Math.PI * 2;
40063 const cx = - tube *
Math.cos(
v );
40064 const cy = tube *
Math.sin(
v );
40069 vertex.x = P1.x + ( cx *
N.x + cy *
B.x );
40070 vertex.y = P1.y + ( cx *
N.y + cy *
B.y );
40071 vertex.z = P1.z + ( cx *
N.z + cy *
B.z );
40073 vertices.push( vertex.x, vertex.y, vertex.z );
40077 normal.subVectors( vertex, P1 ).normalize();
40083 uvs.push(
i / tubularSegments );
40084 uvs.push(
j / radialSegments );
40092 for ( let
j = 1;
j <= tubularSegments;
j ++ ) {
40094 for ( let
i = 1;
i <= radialSegments;
i ++ ) {
40098 const a = ( radialSegments + 1 ) * (
j - 1 ) + (
i - 1 );
40099 const b = ( radialSegments + 1 ) *
j + (
i - 1 );
40100 const c = ( radialSegments + 1 ) *
j +
i;
40101 const d = ( radialSegments + 1 ) * (
j - 1 ) +
i;
40105 indices.push(
a,
b,
d );
40106 indices.push(
b,
c,
d );
40114 this.setIndex( indices );
40115 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
40116 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
40117 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
40121 function calculatePositionOnCurve(
u,
p,
q, radius,
position ) {
40123 const cu =
Math.cos(
u );
40124 const su =
Math.sin(
u );
40125 const quOverP =
q /
p *
u;
40126 const cs =
Math.cos( quOverP );
40128 position.x = radius * ( 2 + cs ) * 0.5 * cu;
40129 position.y = radius * ( 2 + cs ) * su * 0.5;
40138 super.copy( source );
40140 this.parameters = Object.assign( {}, source.parameters );
40146 static fromJSON( data ) {
40148 return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q );
40156 constructor( path =
new QuadraticBezierCurve3(
new Vector3( - 1, - 1, 0 ),
new Vector3( - 1, 1, 0 ),
new Vector3( 1, 1, 0 ) ), tubularSegments = 64, radius = 1, radialSegments = 8, closed =
false ) {
40160 this.type =
'TubeGeometry';
40162 this.parameters = {
40164 tubularSegments: tubularSegments,
40166 radialSegments: radialSegments,
40170 const frames = path.computeFrenetFrames( tubularSegments, closed );
40174 this.tangents = frames.tangents;
40175 this.normals = frames.normals;
40176 this.binormals = frames.binormals;
40180 const vertex =
new Vector3();
40187 const vertices = [];
40188 const normals = [];
40190 const indices = [];
40194 generateBufferData();
40198 this.setIndex( indices );
40199 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
40200 this.setAttribute(
'normal',
new Float32BufferAttribute( normals, 3 ) );
40201 this.setAttribute(
'uv',
new Float32BufferAttribute( uvs, 2 ) );
40205 function generateBufferData() {
40207 for ( let
i = 0;
i < tubularSegments;
i ++ ) {
40209 generateSegment(
i );
40218 generateSegment( ( closed ===
false ) ? tubularSegments : 0 );
40231 function generateSegment(
i ) {
40235 P = path.getPointAt(
i / tubularSegments,
P );
40239 const N = frames.normals[
i ];
40240 const B = frames.binormals[
i ];
40244 for ( let
j = 0;
j <= radialSegments;
j ++ ) {
40246 const v =
j / radialSegments *
Math.PI * 2;
40248 const sin =
Math.sin(
v );
40249 const cos = -
Math.cos(
v );
40253 normal.x = ( cos *
N.x + sin *
B.x );
40254 normal.y = ( cos *
N.y + sin *
B.y );
40255 normal.z = ( cos *
N.z + sin *
B.z );
40262 vertex.x =
P.x + radius *
normal.x;
40263 vertex.y =
P.y + radius *
normal.y;
40264 vertex.z =
P.z + radius *
normal.z;
40266 vertices.push( vertex.x, vertex.y, vertex.z );
40272 function generateIndices() {
40274 for ( let
j = 1;
j <= tubularSegments;
j ++ ) {
40276 for ( let
i = 1;
i <= radialSegments;
i ++ ) {
40278 const a = ( radialSegments + 1 ) * (
j - 1 ) + (
i - 1 );
40279 const b = ( radialSegments + 1 ) *
j + (
i - 1 );
40280 const c = ( radialSegments + 1 ) *
j +
i;
40281 const d = ( radialSegments + 1 ) * (
j - 1 ) +
i;
40285 indices.push(
a,
b,
d );
40286 indices.push(
b,
c,
d );
40294 function generateUVs() {
40296 for ( let
i = 0;
i <= tubularSegments;
i ++ ) {
40298 for ( let
j = 0;
j <= radialSegments;
j ++ ) {
40300 uv.x =
i / tubularSegments;
40301 uv.y =
j / radialSegments;
40303 uvs.push( uv.x, uv.y );
40315 super.copy( source );
40317 this.parameters = Object.assign( {}, source.parameters );
40325 const data = super.toJSON();
40327 data.path = this.parameters.path.toJSON();
40333 static fromJSON( data ) {
40338 new Curves[ data.path.type ]().fromJSON( data.path ),
40339 data.tubularSegments,
40341 data.radialSegments,
40351 constructor( geometry =
null ) {
40355 this.type =
'WireframeGeometry';
40357 this.parameters = {
40361 if ( geometry !==
null ) {
40365 const vertices = [];
40366 const edges =
new Set();
40373 if ( geometry.index !==
null ) {
40377 const position = geometry.attributes.position;
40378 const indices = geometry.index;
40379 let groups = geometry.groups;
40381 if ( groups.length === 0 ) {
40383 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ];
40389 for ( let
o = 0, ol = groups.length;
o < ol; ++
o ) {
40391 const group = groups[
o ];
40393 const groupStart = group.start;
40394 const groupCount = group.count;
40396 for ( let
i = groupStart,
l = ( groupStart + groupCount );
i <
l;
i += 3 ) {
40398 for ( let
j = 0;
j < 3;
j ++ ) {
40400 const index1 = indices.getX(
i +
j );
40401 const index2 = indices.getX(
i + (
j + 1 ) % 3 );
40403 start.fromBufferAttribute(
position, index1 );
40404 end.fromBufferAttribute(
position, index2 );
40406 if ( isUniqueEdge( start, end, edges ) ===
true ) {
40408 vertices.push( start.x, start.y, start.z );
40409 vertices.push( end.x, end.y, end.z );
40423 const position = geometry.attributes.position;
40425 for ( let
i = 0,
l = (
position.count / 3 );
i <
l;
i ++ ) {
40427 for ( let
j = 0;
j < 3;
j ++ ) {
40432 const index1 = 3 *
i +
j;
40433 const index2 = 3 *
i + ( (
j + 1 ) % 3 );
40435 start.fromBufferAttribute(
position, index1 );
40436 end.fromBufferAttribute(
position, index2 );
40438 if ( isUniqueEdge( start, end, edges ) ===
true ) {
40440 vertices.push( start.x, start.y, start.z );
40441 vertices.push( end.x, end.y, end.z );
40453 this.setAttribute(
'position',
new Float32BufferAttribute( vertices, 3 ) );
40461 super.copy( source );
40463 this.parameters = Object.assign( {}, source.parameters );
40471 function isUniqueEdge( start, end, edges ) {
40473 const hash1 = `
${start.x},
${start.y},
${start.z}-
${end.x},
${end.y},
${end.z}`;
40474 const hash2 = `
${end.x},
${end.y},
${end.z}-
${start.x},
${start.y},
${start.z}`;
40476 if ( edges.has( hash1 ) ===
true || edges.has( hash2 ) ===
true ) {
40482 edges.add( hash1 );
40483 edges.add( hash2 );
40490 var Geometries = Object.freeze({
40493 CapsuleGeometry: CapsuleGeometry,
40495 ConeGeometry: ConeGeometry,
40497 DodecahedronGeometry: DodecahedronGeometry,
40498 EdgesGeometry: EdgesGeometry,
40512 WireframeGeometry: WireframeGeometry
40515 class ShadowMaterial
extends Material {
40517 constructor( parameters ) {
40521 this.isShadowMaterial =
true;
40523 this.type =
'ShadowMaterial';
40525 this.color =
new Color( 0x000000 );
40526 this.transparent =
true;
40530 this.setValues( parameters );
40536 super.copy( source );
40538 this.color.copy( source.color );
40540 this.fog = source.fog;
40550 constructor( parameters ) {
40552 super( parameters );
40554 this.isRawShaderMaterial =
true;
40556 this.type =
'RawShaderMaterial';
40562 class MeshStandardMaterial
extends Material {
40564 constructor( parameters ) {
40568 this.isMeshStandardMaterial =
true;
40570 this.defines = {
'STANDARD':
'' };
40572 this.type =
'MeshStandardMaterial';
40574 this.color =
new Color( 0xffffff );
40575 this.roughness = 1.0;
40576 this.metalness = 0.0;
40580 this.lightMap =
null;
40581 this.lightMapIntensity = 1.0;
40584 this.aoMapIntensity = 1.0;
40586 this.emissive =
new Color( 0x000000 );
40587 this.emissiveIntensity = 1.0;
40588 this.emissiveMap =
null;
40590 this.bumpMap =
null;
40591 this.bumpScale = 1;
40593 this.normalMap =
null;
40594 this.normalMapType = TangentSpaceNormalMap;
40595 this.normalScale =
new Vector2( 1, 1 );
40597 this.displacementMap =
null;
40598 this.displacementScale = 1;
40599 this.displacementBias = 0;
40601 this.roughnessMap =
null;
40603 this.metalnessMap =
null;
40605 this.alphaMap =
null;
40607 this.envMap =
null;
40608 this.envMapIntensity = 1.0;
40610 this.wireframe =
false;
40611 this.wireframeLinewidth = 1;
40612 this.wireframeLinecap =
'round';
40613 this.wireframeLinejoin =
'round';
40615 this.flatShading =
false;
40619 this.setValues( parameters );
40625 super.copy( source );
40627 this.defines = {
'STANDARD':
'' };
40629 this.color.copy( source.color );
40630 this.roughness = source.roughness;
40631 this.metalness = source.metalness;
40633 this.map = source.map;
40635 this.lightMap = source.lightMap;
40636 this.lightMapIntensity = source.lightMapIntensity;
40638 this.aoMap = source.aoMap;
40639 this.aoMapIntensity = source.aoMapIntensity;
40641 this.emissive.copy( source.emissive );
40642 this.emissiveMap = source.emissiveMap;
40643 this.emissiveIntensity = source.emissiveIntensity;
40645 this.bumpMap = source.bumpMap;
40646 this.bumpScale = source.bumpScale;
40648 this.normalMap = source.normalMap;
40649 this.normalMapType = source.normalMapType;
40650 this.normalScale.copy( source.normalScale );
40652 this.displacementMap = source.displacementMap;
40653 this.displacementScale = source.displacementScale;
40654 this.displacementBias = source.displacementBias;
40656 this.roughnessMap = source.roughnessMap;
40658 this.metalnessMap = source.metalnessMap;
40660 this.alphaMap = source.alphaMap;
40662 this.envMap = source.envMap;
40663 this.envMapIntensity = source.envMapIntensity;
40665 this.wireframe = source.wireframe;
40666 this.wireframeLinewidth = source.wireframeLinewidth;
40667 this.wireframeLinecap = source.wireframeLinecap;
40668 this.wireframeLinejoin = source.wireframeLinejoin;
40670 this.flatShading = source.flatShading;
40672 this.fog = source.fog;
40680 class MeshPhysicalMaterial
extends MeshStandardMaterial {
40682 constructor( parameters ) {
40686 this.isMeshPhysicalMaterial =
true;
40695 this.type =
'MeshPhysicalMaterial';
40697 this.anisotropyRotation = 0;
40698 this.anisotropyMap =
null;
40700 this.clearcoatMap =
null;
40701 this.clearcoatRoughness = 0.0;
40702 this.clearcoatRoughnessMap =
null;
40703 this.clearcoatNormalScale =
new Vector2( 1, 1 );
40704 this.clearcoatNormalMap =
null;
40708 Object.defineProperty(
this,
'reflectivity', {
40711 return ( clamp( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) );
40714 set:
function ( reflectivity ) {
40716 this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity );
40721 this.iridescenceMap =
null;
40722 this.iridescenceIOR = 1.3;
40723 this.iridescenceThicknessRange = [ 100, 400 ];
40724 this.iridescenceThicknessMap =
null;
40726 this.sheenColor =
new Color( 0x000000 );
40727 this.sheenColorMap =
null;
40728 this.sheenRoughness = 1.0;
40729 this.sheenRoughnessMap =
null;
40731 this.transmissionMap =
null;
40733 this.thickness = 0;
40734 this.thicknessMap =
null;
40735 this.attenuationDistance = Infinity;
40736 this.attenuationColor =
new Color( 1, 1, 1 );
40738 this.specularIntensity = 1.0;
40739 this.specularIntensityMap =
null;
40740 this.specularColor =
new Color( 1, 1, 1 );
40741 this.specularColorMap =
null;
40743 this._anisotropy = 0;
40744 this._clearcoat = 0;
40745 this._iridescence = 0;
40747 this._transmission = 0;
40749 this.setValues( parameters );
40755 return this._anisotropy;
40759 set anisotropy( value ) {
40761 if ( this._anisotropy > 0 !== value > 0 ) {
40767 this._anisotropy = value;
40773 return this._clearcoat;
40777 set clearcoat( value ) {
40779 if ( this._clearcoat > 0 !== value > 0 ) {
40785 this._clearcoat = value;
40789 get iridescence() {
40791 return this._iridescence;
40795 set iridescence( value ) {
40797 if ( this._iridescence > 0 !== value > 0 ) {
40803 this._iridescence = value;
40809 return this._sheen;
40813 set sheen( value ) {
40815 if ( this._sheen > 0 !== value > 0 ) {
40821 this._sheen = value;
40825 get transmission() {
40827 return this._transmission;
40831 set transmission( value ) {
40833 if ( this._transmission > 0 !== value > 0 ) {
40839 this._transmission = value;
40845 super.copy( source );
40854 this.anisotropy = source.anisotropy;
40855 this.anisotropyRotation = source.anisotropyRotation;
40856 this.anisotropyMap = source.anisotropyMap;
40858 this.clearcoat = source.clearcoat;
40859 this.clearcoatMap = source.clearcoatMap;
40860 this.clearcoatRoughness = source.clearcoatRoughness;
40861 this.clearcoatRoughnessMap = source.clearcoatRoughnessMap;
40862 this.clearcoatNormalMap = source.clearcoatNormalMap;
40863 this.clearcoatNormalScale.copy( source.clearcoatNormalScale );
40865 this.ior = source.ior;
40867 this.iridescence = source.iridescence;
40868 this.iridescenceMap = source.iridescenceMap;
40869 this.iridescenceIOR = source.iridescenceIOR;
40870 this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ];
40871 this.iridescenceThicknessMap = source.iridescenceThicknessMap;
40873 this.sheen = source.sheen;
40874 this.sheenColor.copy( source.sheenColor );
40875 this.sheenColorMap = source.sheenColorMap;
40876 this.sheenRoughness = source.sheenRoughness;
40877 this.sheenRoughnessMap = source.sheenRoughnessMap;
40879 this.transmission = source.transmission;
40880 this.transmissionMap = source.transmissionMap;
40882 this.thickness = source.thickness;
40883 this.thicknessMap = source.thicknessMap;
40884 this.attenuationDistance = source.attenuationDistance;
40885 this.attenuationColor.copy( source.attenuationColor );
40887 this.specularIntensity = source.specularIntensity;
40888 this.specularIntensityMap = source.specularIntensityMap;
40889 this.specularColor.copy( source.specularColor );
40890 this.specularColorMap = source.specularColorMap;
40900 constructor( parameters ) {
40904 this.isMeshPhongMaterial =
true;
40906 this.type =
'MeshPhongMaterial';
40908 this.color =
new Color( 0xffffff );
40909 this.specular =
new Color( 0x111111 );
40910 this.shininess = 30;
40914 this.lightMap =
null;
40915 this.lightMapIntensity = 1.0;
40918 this.aoMapIntensity = 1.0;
40920 this.emissive =
new Color( 0x000000 );
40921 this.emissiveIntensity = 1.0;
40922 this.emissiveMap =
null;
40924 this.bumpMap =
null;
40925 this.bumpScale = 1;
40927 this.normalMap =
null;
40928 this.normalMapType = TangentSpaceNormalMap;
40929 this.normalScale =
new Vector2( 1, 1 );
40931 this.displacementMap =
null;
40932 this.displacementScale = 1;
40933 this.displacementBias = 0;
40935 this.specularMap =
null;
40937 this.alphaMap =
null;
40939 this.envMap =
null;
40941 this.reflectivity = 1;
40942 this.refractionRatio = 0.98;
40944 this.wireframe =
false;
40945 this.wireframeLinewidth = 1;
40946 this.wireframeLinecap =
'round';
40947 this.wireframeLinejoin =
'round';
40949 this.flatShading =
false;
40953 this.setValues( parameters );
40959 super.copy( source );
40961 this.color.copy( source.color );
40962 this.specular.copy( source.specular );
40963 this.shininess = source.shininess;
40965 this.map = source.map;
40967 this.lightMap = source.lightMap;
40968 this.lightMapIntensity = source.lightMapIntensity;
40970 this.aoMap = source.aoMap;
40971 this.aoMapIntensity = source.aoMapIntensity;
40973 this.emissive.copy( source.emissive );
40974 this.emissiveMap = source.emissiveMap;
40975 this.emissiveIntensity = source.emissiveIntensity;
40977 this.bumpMap = source.bumpMap;
40978 this.bumpScale = source.bumpScale;
40980 this.normalMap = source.normalMap;
40981 this.normalMapType = source.normalMapType;
40982 this.normalScale.copy( source.normalScale );
40984 this.displacementMap = source.displacementMap;
40985 this.displacementScale = source.displacementScale;
40986 this.displacementBias = source.displacementBias;
40988 this.specularMap = source.specularMap;
40990 this.alphaMap = source.alphaMap;
40992 this.envMap = source.envMap;
40993 this.combine = source.combine;
40994 this.reflectivity = source.reflectivity;
40995 this.refractionRatio = source.refractionRatio;
40997 this.wireframe = source.wireframe;
40998 this.wireframeLinewidth = source.wireframeLinewidth;
40999 this.wireframeLinecap = source.wireframeLinecap;
41000 this.wireframeLinejoin = source.wireframeLinejoin;
41002 this.flatShading = source.flatShading;
41004 this.fog = source.fog;
41012 class MeshToonMaterial
extends Material {
41014 constructor( parameters ) {
41018 this.isMeshToonMaterial =
true;
41020 this.defines = {
'TOON':
'' };
41022 this.type =
'MeshToonMaterial';
41024 this.color =
new Color( 0xffffff );
41027 this.gradientMap =
null;
41029 this.lightMap =
null;
41030 this.lightMapIntensity = 1.0;
41033 this.aoMapIntensity = 1.0;
41035 this.emissive =
new Color( 0x000000 );
41036 this.emissiveIntensity = 1.0;
41037 this.emissiveMap =
null;
41039 this.bumpMap =
null;
41040 this.bumpScale = 1;
41042 this.normalMap =
null;
41043 this.normalMapType = TangentSpaceNormalMap;
41044 this.normalScale =
new Vector2( 1, 1 );
41046 this.displacementMap =
null;
41047 this.displacementScale = 1;
41048 this.displacementBias = 0;
41050 this.alphaMap =
null;
41052 this.wireframe =
false;
41053 this.wireframeLinewidth = 1;
41054 this.wireframeLinecap =
'round';
41055 this.wireframeLinejoin =
'round';
41059 this.setValues( parameters );
41065 super.copy( source );
41067 this.color.copy( source.color );
41069 this.map = source.map;
41070 this.gradientMap = source.gradientMap;
41072 this.lightMap = source.lightMap;
41073 this.lightMapIntensity = source.lightMapIntensity;
41075 this.aoMap = source.aoMap;
41076 this.aoMapIntensity = source.aoMapIntensity;
41078 this.emissive.copy( source.emissive );
41079 this.emissiveMap = source.emissiveMap;
41080 this.emissiveIntensity = source.emissiveIntensity;
41082 this.bumpMap = source.bumpMap;
41083 this.bumpScale = source.bumpScale;
41085 this.normalMap = source.normalMap;
41086 this.normalMapType = source.normalMapType;
41087 this.normalScale.copy( source.normalScale );
41089 this.displacementMap = source.displacementMap;
41090 this.displacementScale = source.displacementScale;
41091 this.displacementBias = source.displacementBias;
41093 this.alphaMap = source.alphaMap;
41095 this.wireframe = source.wireframe;
41096 this.wireframeLinewidth = source.wireframeLinewidth;
41097 this.wireframeLinecap = source.wireframeLinecap;
41098 this.wireframeLinejoin = source.wireframeLinejoin;
41100 this.fog = source.fog;
41110 constructor( parameters ) {
41114 this.isMeshNormalMaterial =
true;
41116 this.type =
'MeshNormalMaterial';
41118 this.bumpMap =
null;
41119 this.bumpScale = 1;
41121 this.normalMap =
null;
41122 this.normalMapType = TangentSpaceNormalMap;
41123 this.normalScale =
new Vector2( 1, 1 );
41125 this.displacementMap =
null;
41126 this.displacementScale = 1;
41127 this.displacementBias = 0;
41129 this.wireframe =
false;
41130 this.wireframeLinewidth = 1;
41132 this.flatShading =
false;
41134 this.setValues( parameters );
41140 super.copy( source );
41142 this.bumpMap = source.bumpMap;
41143 this.bumpScale = source.bumpScale;
41145 this.normalMap = source.normalMap;
41146 this.normalMapType = source.normalMapType;
41147 this.normalScale.copy( source.normalScale );
41149 this.displacementMap = source.displacementMap;
41150 this.displacementScale = source.displacementScale;
41151 this.displacementBias = source.displacementBias;
41153 this.wireframe = source.wireframe;
41154 this.wireframeLinewidth = source.wireframeLinewidth;
41156 this.flatShading = source.flatShading;
41166 constructor( parameters ) {
41170 this.isMeshLambertMaterial =
true;
41172 this.type =
'MeshLambertMaterial';
41174 this.color =
new Color( 0xffffff );
41178 this.lightMap =
null;
41179 this.lightMapIntensity = 1.0;
41182 this.aoMapIntensity = 1.0;
41184 this.emissive =
new Color( 0x000000 );
41185 this.emissiveIntensity = 1.0;
41186 this.emissiveMap =
null;
41188 this.bumpMap =
null;
41189 this.bumpScale = 1;
41191 this.normalMap =
null;
41192 this.normalMapType = TangentSpaceNormalMap;
41193 this.normalScale =
new Vector2( 1, 1 );
41195 this.displacementMap =
null;
41196 this.displacementScale = 1;
41197 this.displacementBias = 0;
41199 this.specularMap =
null;
41201 this.alphaMap =
null;
41203 this.envMap =
null;
41205 this.reflectivity = 1;
41206 this.refractionRatio = 0.98;
41208 this.wireframe =
false;
41209 this.wireframeLinewidth = 1;
41210 this.wireframeLinecap =
'round';
41211 this.wireframeLinejoin =
'round';
41213 this.flatShading =
false;
41217 this.setValues( parameters );
41223 super.copy( source );
41225 this.color.copy( source.color );
41227 this.map = source.map;
41229 this.lightMap = source.lightMap;
41230 this.lightMapIntensity = source.lightMapIntensity;
41232 this.aoMap = source.aoMap;
41233 this.aoMapIntensity = source.aoMapIntensity;
41235 this.emissive.copy( source.emissive );
41236 this.emissiveMap = source.emissiveMap;
41237 this.emissiveIntensity = source.emissiveIntensity;
41239 this.bumpMap = source.bumpMap;
41240 this.bumpScale = source.bumpScale;
41242 this.normalMap = source.normalMap;
41243 this.normalMapType = source.normalMapType;
41244 this.normalScale.copy( source.normalScale );
41246 this.displacementMap = source.displacementMap;
41247 this.displacementScale = source.displacementScale;
41248 this.displacementBias = source.displacementBias;
41250 this.specularMap = source.specularMap;
41252 this.alphaMap = source.alphaMap;
41254 this.envMap = source.envMap;
41255 this.combine = source.combine;
41256 this.reflectivity = source.reflectivity;
41257 this.refractionRatio = source.refractionRatio;
41259 this.wireframe = source.wireframe;
41260 this.wireframeLinewidth = source.wireframeLinewidth;
41261 this.wireframeLinecap = source.wireframeLinecap;
41262 this.wireframeLinejoin = source.wireframeLinejoin;
41264 this.flatShading = source.flatShading;
41266 this.fog = source.fog;
41274 class MeshMatcapMaterial
extends Material {
41276 constructor( parameters ) {
41280 this.isMeshMatcapMaterial =
true;
41282 this.defines = {
'MATCAP':
'' };
41284 this.type =
'MeshMatcapMaterial';
41286 this.color =
new Color( 0xffffff );
41288 this.matcap =
null;
41292 this.bumpMap =
null;
41293 this.bumpScale = 1;
41295 this.normalMap =
null;
41296 this.normalMapType = TangentSpaceNormalMap;
41297 this.normalScale =
new Vector2( 1, 1 );
41299 this.displacementMap =
null;
41300 this.displacementScale = 1;
41301 this.displacementBias = 0;
41303 this.alphaMap =
null;
41305 this.flatShading =
false;
41309 this.setValues( parameters );
41316 super.copy( source );
41318 this.defines = {
'MATCAP':
'' };
41320 this.color.copy( source.color );
41322 this.matcap = source.matcap;
41324 this.map = source.map;
41326 this.bumpMap = source.bumpMap;
41327 this.bumpScale = source.bumpScale;
41329 this.normalMap = source.normalMap;
41330 this.normalMapType = source.normalMapType;
41331 this.normalScale.copy( source.normalScale );
41333 this.displacementMap = source.displacementMap;
41334 this.displacementScale = source.displacementScale;
41335 this.displacementBias = source.displacementBias;
41337 this.alphaMap = source.alphaMap;
41339 this.flatShading = source.flatShading;
41341 this.fog = source.fog;
41351 constructor( parameters ) {
41355 this.isLineDashedMaterial =
true;
41357 this.type =
'LineDashedMaterial';
41363 this.setValues( parameters );
41369 super.copy( source );
41371 this.scale = source.scale;
41372 this.dashSize = source.dashSize;
41373 this.gapSize = source.gapSize;
41382 function convertArray( array, type, forceClone ) {
41385 ! forceClone && array.constructor === type )
return array;
41387 if ( typeof type.BYTES_PER_ELEMENT ===
'number' ) {
41389 return new type( array );
41393 return Array.prototype.slice.call( array );
41397 function isTypedArray(
object ) {
41399 return ArrayBuffer.isView(
object ) &&
41405 function getKeyframeOrder( times ) {
41407 function compareTime(
i,
j ) {
41409 return times[
i ] - times[
j ];
41413 const n = times.length;
41414 const result =
new Array(
n );
41415 for ( let
i = 0;
i !==
n; ++
i ) result[
i ] =
i;
41417 result.sort( compareTime );
41424 function sortedArray( values, stride, order ) {
41426 const nValues = values.length;
41427 const result =
new values.constructor( nValues );
41429 for ( let
i = 0, dstOffset = 0; dstOffset !== nValues; ++
i ) {
41431 const srcOffset = order[
i ] * stride;
41433 for ( let
j = 0;
j !== stride; ++
j ) {
41435 result[ dstOffset ++ ] = values[ srcOffset +
j ];
41446 function flattenJSON( jsonKeys, times, values, valuePropertyName ) {
41448 let
i = 1, key = jsonKeys[ 0 ];
41452 key = jsonKeys[
i ++ ];
41458 let value = key[ valuePropertyName ];
41461 if (
Array.isArray( value ) ) {
41465 value = key[ valuePropertyName ];
41469 times.push( key.time );
41470 values.push.apply( values, value );
41474 key = jsonKeys[
i ++ ];
41478 }
else if ( value.toArray !==
undefined ) {
41484 value = key[ valuePropertyName ];
41488 times.push( key.time );
41489 value.toArray( values, values.length );
41493 key = jsonKeys[
i ++ ];
41503 value = key[ valuePropertyName ];
41507 times.push( key.time );
41508 values.push( value );
41512 key = jsonKeys[
i ++ ];
41520 function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) {
41522 const clip = sourceClip.clone();
41528 for ( let
i = 0;
i < clip.tracks.length; ++
i ) {
41530 const track = clip.tracks[
i ];
41531 const valueSize = track.getValueSize();
41536 for ( let
j = 0;
j < track.times.length; ++
j ) {
41538 const frame = track.times[
j ] * fps;
41540 if ( frame < startFrame || frame >= endFrame )
continue;
41542 times.push( track.times[
j ] );
41544 for ( let
k = 0;
k < valueSize; ++
k ) {
41546 values.push( track.values[
j * valueSize +
k ] );
41552 if ( times.length === 0 )
continue;
41554 track.times = convertArray( times, track.times.constructor );
41555 track.values = convertArray( values, track.values.constructor );
41557 tracks.push( track );
41561 clip.tracks = tracks;
41565 let minStartTime = Infinity;
41567 for ( let
i = 0;
i < clip.tracks.length; ++
i ) {
41569 if ( minStartTime > clip.tracks[
i ].times[ 0 ] ) {
41571 minStartTime = clip.tracks[
i ].times[ 0 ];
41579 for ( let
i = 0;
i < clip.tracks.length; ++
i ) {
41581 clip.tracks[
i ].shift( - 1 * minStartTime );
41585 clip.resetDuration();
41591 function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) {
41593 if ( fps <= 0 ) fps = 30;
41595 const numTracks = referenceClip.tracks.length;
41596 const referenceTime = referenceFrame / fps;
41599 for ( let
i = 0;
i < numTracks; ++
i ) {
41601 const referenceTrack = referenceClip.tracks[
i ];
41602 const referenceTrackType = referenceTrack.ValueTypeName;
41605 if ( referenceTrackType ===
'bool' || referenceTrackType ===
'string' )
continue;
41608 const targetTrack = targetClip.tracks.find(
function ( track ) {
41610 return track.name === referenceTrack.name
41611 && track.ValueTypeName === referenceTrackType;
41615 if ( targetTrack ===
undefined )
continue;
41617 let referenceOffset = 0;
41618 const referenceValueSize = referenceTrack.getValueSize();
41620 if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
41622 referenceOffset = referenceValueSize / 3;
41626 let targetOffset = 0;
41627 const targetValueSize = targetTrack.getValueSize();
41629 if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) {
41631 targetOffset = targetValueSize / 3;
41635 const lastIndex = referenceTrack.times.length - 1;
41636 let referenceValue;
41639 if ( referenceTime <= referenceTrack.times[ 0 ] ) {
41642 const startIndex = referenceOffset;
41643 const endIndex = referenceValueSize - referenceOffset;
41644 referenceValue = referenceTrack.values.slice( startIndex, endIndex );
41646 }
else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) {
41649 const startIndex = lastIndex * referenceValueSize + referenceOffset;
41650 const endIndex = startIndex + referenceValueSize - referenceOffset;
41651 referenceValue = referenceTrack.values.slice( startIndex, endIndex );
41656 const interpolant = referenceTrack.createInterpolant();
41657 const startIndex = referenceOffset;
41658 const endIndex = referenceValueSize - referenceOffset;
41659 interpolant.evaluate( referenceTime );
41660 referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex );
41665 if ( referenceTrackType ===
'quaternion' ) {
41667 const referenceQuat =
new Quaternion().fromArray( referenceValue ).normalize().conjugate();
41668 referenceQuat.toArray( referenceValue );
41674 const numTimes = targetTrack.times.length;
41675 for ( let
j = 0;
j < numTimes; ++
j ) {
41677 const valueStart =
j * targetValueSize + targetOffset;
41679 if ( referenceTrackType ===
'quaternion' ) {
41683 targetTrack.values,
41687 targetTrack.values,
41693 const valueEnd = targetValueSize - targetOffset * 2;
41696 for ( let
k = 0;
k < valueEnd; ++
k ) {
41698 targetTrack.values[ valueStart +
k ] -= referenceValue[
k ];
41708 targetClip.blendMode = AdditiveAnimationBlendMode;
41714 const AnimationUtils = {
41715 convertArray: convertArray,
41716 isTypedArray: isTypedArray,
41717 getKeyframeOrder: getKeyframeOrder,
41718 sortedArray: sortedArray,
41719 flattenJSON: flattenJSON,
41721 makeClipAdditive: makeClipAdditive
41745 class Interpolant {
41747 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41749 this.parameterPositions = parameterPositions;
41750 this._cachedIndex = 0;
41752 this.resultBuffer = resultBuffer !==
undefined ?
41753 resultBuffer :
new sampleValues.constructor( sampleSize );
41754 this.sampleValues = sampleValues;
41755 this.valueSize = sampleSize;
41757 this.settings =
null;
41758 this.DefaultSettings_ = {};
41764 const pp = this.parameterPositions;
41765 let i1 = this._cachedIndex,
41769 validate_interval: {
41781 forward_scan:
if ( ! (
t < t1 ) ) {
41783 for ( let giveUpAt = i1 + 2; ; ) {
41787 if (
t < t0 )
break forward_scan;
41792 this._cachedIndex = i1;
41793 return this.copySampleValue_( i1 - 1 );
41797 if ( i1 === giveUpAt )
break;
41819 if ( ! (
t >= t0 ) ) {
41823 const t1global = pp[ 1 ];
41825 if (
t < t1global ) {
41834 for ( let giveUpAt = i1 - 2; ; ) {
41840 this._cachedIndex = 0;
41841 return this.copySampleValue_( 0 );
41845 if ( i1 === giveUpAt )
break;
41848 t0 = pp[ -- i1 - 1 ];
41868 break validate_interval;
41874 while ( i1 < right ) {
41876 const mid = ( i1 + right ) >>> 1;
41878 if (
t < pp[ mid ] ) {
41897 this._cachedIndex = 0;
41898 return this.copySampleValue_( 0 );
41905 this._cachedIndex = i1;
41906 return this.copySampleValue_( i1 - 1 );
41912 this._cachedIndex = i1;
41914 this.intervalChanged_( i1, t0, t1 );
41918 return this.interpolate_( i1, t0,
t, t1 );
41924 return this.settings || this.DefaultSettings_;
41928 copySampleValue_( index ) {
41932 const result = this.resultBuffer,
41933 values = this.sampleValues,
41934 stride = this.valueSize,
41935 offset = index * stride;
41937 for ( let
i = 0;
i !== stride; ++
i ) {
41939 result[
i ] = values[ offset +
i ];
41951 throw new Error(
'call to abstract method' );
41956 intervalChanged_( ) {
41972 class CubicInterpolant
extends Interpolant {
41974 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
41976 super( parameterPositions, sampleValues, sampleSize, resultBuffer );
41978 this._weightPrev = - 0;
41979 this._offsetPrev = - 0;
41980 this._weightNext = - 0;
41981 this._offsetNext = - 0;
41983 this.DefaultSettings_ = {
41985 endingStart: ZeroCurvatureEnding,
41986 endingEnd: ZeroCurvatureEnding
41992 intervalChanged_( i1, t0, t1 ) {
41994 const pp = this.parameterPositions;
41995 let iPrev = i1 - 2,
41998 tPrev = pp[ iPrev ],
41999 tNext = pp[ iNext ];
42003 switch ( this.getSettings_().endingStart ) {
42005 case ZeroSlopeEnding:
42009 tPrev = 2 * t0 - t1;
42013 case WrapAroundEnding:
42016 iPrev = pp.length - 2;
42017 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ];
42033 switch ( this.getSettings_().endingEnd ) {
42035 case ZeroSlopeEnding:
42039 tNext = 2 * t1 - t0;
42043 case WrapAroundEnding:
42047 tNext = t1 + pp[ 1 ] - pp[ 0 ];
42061 const halfDt = ( t1 - t0 ) * 0.5,
42062 stride = this.valueSize;
42064 this._weightPrev = halfDt / ( t0 - tPrev );
42065 this._weightNext = halfDt / ( tNext - t1 );
42066 this._offsetPrev = iPrev * stride;
42067 this._offsetNext = iNext * stride;
42071 interpolate_( i1, t0,
t, t1 ) {
42073 const result = this.resultBuffer,
42074 values = this.sampleValues,
42075 stride = this.valueSize,
42077 o1 = i1 * stride, o0 = o1 - stride,
42078 oP = this._offsetPrev, oN = this._offsetNext,
42079 wP = this._weightPrev, wN = this._weightNext,
42081 p = (
t - t0 ) / ( t1 - t0 ),
42087 const sP = - wP * ppp + 2 * wP * pp - wP *
p;
42088 const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) *
p + 1;
42089 const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 *
p;
42090 const sN = wN * ppp - wN * pp;
42094 for ( let
i = 0;
i !== stride; ++
i ) {
42097 sP * values[ oP +
i ] +
42098 s0 * values[ o0 +
i ] +
42099 s1 * values[ o1 +
i ] +
42100 sN * values[ oN +
i ];
42110 class LinearInterpolant
extends Interpolant {
42112 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42114 super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42118 interpolate_( i1, t0,
t, t1 ) {
42120 const result = this.resultBuffer,
42121 values = this.sampleValues,
42122 stride = this.valueSize,
42124 offset1 = i1 * stride,
42125 offset0 = offset1 - stride,
42127 weight1 = (
t - t0 ) / ( t1 - t0 ),
42128 weight0 = 1 - weight1;
42130 for ( let
i = 0;
i !== stride; ++
i ) {
42133 values[ offset0 +
i ] * weight0 +
42134 values[ offset1 +
i ] * weight1;
42150 class DiscreteInterpolant
extends Interpolant {
42152 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42154 super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42158 interpolate_( i1 ) {
42160 return this.copySampleValue_( i1 - 1 );
42166 class KeyframeTrack {
42168 constructor( name, times, values, interpolation ) {
42170 if ( name ===
undefined )
throw new Error(
'THREE.KeyframeTrack: track name is undefined' );
42171 if ( times ===
undefined || times.length === 0 )
throw new Error(
'THREE.KeyframeTrack: no keyframes in track named ' + name );
42175 this.times = convertArray( times, this.TimeBufferType );
42176 this.values = convertArray( values, this.ValueBufferType );
42178 this.setInterpolation( interpolation || this.DefaultInterpolation );
42185 static toJSON( track ) {
42187 const trackType = track.constructor;
42192 if ( trackType.toJSON !==
this.toJSON ) {
42194 json = trackType.toJSON( track );
42201 'name': track.name,
42202 'times': convertArray( track.times,
Array ),
42203 'values': convertArray( track.values,
Array )
42207 const interpolation = track.getInterpolation();
42209 if ( interpolation !== track.DefaultInterpolation ) {
42211 json.interpolation = interpolation;
42217 json.type = track.ValueTypeName;
42223 InterpolantFactoryMethodDiscrete( result ) {
42225 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result );
42229 InterpolantFactoryMethodLinear( result ) {
42231 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result );
42235 InterpolantFactoryMethodSmooth( result ) {
42237 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result );
42241 setInterpolation( interpolation ) {
42245 switch ( interpolation ) {
42247 case InterpolateDiscrete:
42249 factoryMethod = this.InterpolantFactoryMethodDiscrete;
42253 case InterpolateLinear:
42255 factoryMethod = this.InterpolantFactoryMethodLinear;
42259 case InterpolateSmooth:
42261 factoryMethod = this.InterpolantFactoryMethodSmooth;
42269 const message =
'unsupported interpolation for ' +
42270 this.ValueTypeName +
' keyframe track named ' + this.name;
42272 if ( this.createInterpolant ===
undefined ) {
42275 if ( interpolation !== this.DefaultInterpolation ) {
42277 this.setInterpolation( this.DefaultInterpolation );
42281 throw new Error( message );
42287 console.warn(
'THREE.KeyframeTrack:', message );
42292 this.createInterpolant = factoryMethod;
42298 getInterpolation() {
42300 switch ( this.createInterpolant ) {
42302 case this.InterpolantFactoryMethodDiscrete:
42304 return InterpolateDiscrete;
42306 case this.InterpolantFactoryMethodLinear:
42308 return InterpolateLinear;
42310 case this.InterpolantFactoryMethodSmooth:
42312 return InterpolateSmooth;
42320 return this.values.length / this.times.length;
42325 shift( timeOffset ) {
42327 if ( timeOffset !== 0.0 ) {
42329 const times = this.times;
42331 for ( let
i = 0,
n = times.length;
i !==
n; ++
i ) {
42333 times[
i ] += timeOffset;
42344 scale( timeScale ) {
42346 if ( timeScale !== 1.0 ) {
42348 const times = this.times;
42350 for ( let
i = 0,
n = times.length;
i !==
n; ++
i ) {
42352 times[
i ] *= timeScale;
42364 trim( startTime, endTime ) {
42366 const times = this.times,
42367 nKeys = times.length;
42372 while ( from !== nKeys && times[ from ] < startTime ) {
42378 while ( to !== - 1 && times[ to ] > endTime ) {
42386 if ( from !== 0 || to !== nKeys ) {
42389 if ( from >= to ) {
42391 to =
Math.max( to, 1 );
42396 const stride = this.getValueSize();
42397 this.times = times.slice( from, to );
42398 this.values = this.values.slice( from * stride, to * stride );
42411 const valueSize = this.getValueSize();
42412 if ( valueSize -
Math.floor( valueSize ) !== 0 ) {
42414 console.error(
'THREE.KeyframeTrack: Invalid value size in track.',
this );
42419 const times = this.times,
42420 values = this.values,
42422 nKeys = times.length;
42424 if ( nKeys === 0 ) {
42426 console.error(
'THREE.KeyframeTrack: Track is empty.',
this );
42431 let prevTime =
null;
42433 for ( let
i = 0;
i !== nKeys;
i ++ ) {
42435 const currTime = times[
i ];
42437 if ( typeof currTime ===
'number' && isNaN( currTime ) ) {
42439 console.error(
'THREE.KeyframeTrack: Time is not a valid number.',
this,
i, currTime );
42445 if ( prevTime !==
null && prevTime > currTime ) {
42447 console.error(
'THREE.KeyframeTrack: Out of order keys.',
this,
i, currTime, prevTime );
42453 prevTime = currTime;
42459 if ( isTypedArray( values ) ) {
42461 for ( let
i = 0,
n = values.length;
i !==
n; ++
i ) {
42463 const value = values[
i ];
42465 if ( isNaN( value ) ) {
42467 console.error(
'THREE.KeyframeTrack: Value is not a valid number.',
this,
i, value );
42488 const times = this.times.slice(),
42489 values = this.values.slice(),
42490 stride = this.getValueSize(),
42492 smoothInterpolation = this.getInterpolation() === InterpolateSmooth,
42494 lastIndex = times.length - 1;
42496 let writeIndex = 1;
42498 for ( let
i = 1;
i < lastIndex; ++
i ) {
42502 const time = times[
i ];
42503 const timeNext = times[
i + 1 ];
42507 if ( time !== timeNext && (
i !== 1 || time !== times[ 0 ] ) ) {
42509 if ( ! smoothInterpolation ) {
42513 const offset =
i * stride,
42514 offsetP = offset - stride,
42515 offsetN = offset + stride;
42517 for ( let
j = 0;
j !== stride; ++
j ) {
42519 const value = values[ offset +
j ];
42521 if ( value !== values[ offsetP +
j ] ||
42522 value !== values[ offsetN +
j ] ) {
42543 if (
i !== writeIndex ) {
42545 times[ writeIndex ] = times[
i ];
42547 const readOffset =
i * stride,
42548 writeOffset = writeIndex * stride;
42550 for ( let
j = 0;
j !== stride; ++
j ) {
42552 values[ writeOffset +
j ] = values[ readOffset +
j ];
42566 if ( lastIndex > 0 ) {
42568 times[ writeIndex ] = times[ lastIndex ];
42570 for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride,
j = 0;
j !== stride; ++
j ) {
42572 values[ writeOffset +
j ] = values[ readOffset +
j ];
42580 if ( writeIndex !== times.length ) {
42582 this.times = times.slice( 0, writeIndex );
42583 this.values = values.slice( 0, writeIndex * stride );
42587 this.times = times;
42588 this.values = values;
42598 const times = this.times.slice();
42599 const values = this.values.slice();
42601 const TypedKeyframeTrack = this.constructor;
42602 const track =
new TypedKeyframeTrack( this.name, times, values );
42605 track.createInterpolant = this.createInterpolant;
42613 KeyframeTrack.prototype.TimeBufferType =
Float32Array;
42614 KeyframeTrack.prototype.ValueBufferType =
Float32Array;
42615 KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
42620 class BooleanKeyframeTrack
extends KeyframeTrack {}
42622 BooleanKeyframeTrack.prototype.ValueTypeName =
'bool';
42623 BooleanKeyframeTrack.prototype.ValueBufferType =
Array;
42624 BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42625 BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear =
undefined;
42626 BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth =
undefined;
42631 class ColorKeyframeTrack
extends KeyframeTrack {}
42633 ColorKeyframeTrack.prototype.ValueTypeName =
'color';
42638 class NumberKeyframeTrack
extends KeyframeTrack {}
42640 NumberKeyframeTrack.prototype.ValueTypeName =
'number';
42646 class QuaternionLinearInterpolant
extends Interpolant {
42648 constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
42650 super( parameterPositions, sampleValues, sampleSize, resultBuffer );
42654 interpolate_( i1, t0,
t, t1 ) {
42656 const result = this.resultBuffer,
42657 values = this.sampleValues,
42658 stride = this.valueSize,
42660 alpha = (
t - t0 ) / ( t1 - t0 );
42662 let offset = i1 * stride;
42664 for ( let end = offset + stride; offset !== end; offset += 4 ) {
42666 Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha );
42679 class QuaternionKeyframeTrack
extends KeyframeTrack {
42681 InterpolantFactoryMethodLinear( result ) {
42683 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result );
42689 QuaternionKeyframeTrack.prototype.ValueTypeName =
'quaternion';
42691 QuaternionKeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear;
42692 QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth =
undefined;
42697 class StringKeyframeTrack
extends KeyframeTrack {}
42699 StringKeyframeTrack.prototype.ValueTypeName =
'string';
42700 StringKeyframeTrack.prototype.ValueBufferType =
Array;
42701 StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete;
42702 StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear =
undefined;
42703 StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth =
undefined;
42708 class VectorKeyframeTrack
extends KeyframeTrack {}
42710 VectorKeyframeTrack.prototype.ValueTypeName =
'vector';
42712 class AnimationClip {
42714 constructor( name, duration = - 1, tracks, blendMode = NormalAnimationBlendMode ) {
42717 this.tracks = tracks;
42718 this.duration = duration;
42719 this.blendMode = blendMode;
42721 this.uuid = generateUUID();
42724 if ( this.duration < 0 ) {
42726 this.resetDuration();
42733 static parse( json ) {
42736 jsonTracks = json.tracks,
42737 frameTime = 1.0 / ( json.fps || 1.0 );
42739 for ( let
i = 0,
n = jsonTracks.length;
i !==
n; ++
i ) {
42741 tracks.push( parseKeyframeTrack( jsonTracks[
i ] ).scale( frameTime ) );
42745 const clip =
new this( json.name, json.duration, tracks, json.blendMode );
42746 clip.uuid = json.uuid;
42752 static toJSON( clip ) {
42755 clipTracks = clip.tracks;
42760 'duration': clip.duration,
42763 'blendMode': clip.blendMode
42767 for ( let
i = 0,
n = clipTracks.length;
i !==
n; ++
i ) {
42769 tracks.push( KeyframeTrack.toJSON( clipTracks[
i ] ) );
42777 static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) {
42779 const numMorphTargets = morphTargetSequence.length;
42782 for ( let
i = 0;
i < numMorphTargets;
i ++ ) {
42788 (
i + numMorphTargets - 1 ) % numMorphTargets,
42790 (
i + 1 ) % numMorphTargets );
42792 values.push( 0, 1, 0 );
42794 const order = getKeyframeOrder( times );
42795 times = sortedArray( times, 1, order );
42796 values = sortedArray( values, 1, order );
42800 if ( ! noLoop && times[ 0 ] === 0 ) {
42802 times.push( numMorphTargets );
42803 values.push( values[ 0 ] );
42808 new NumberKeyframeTrack(
42809 '.morphTargetInfluences[' + morphTargetSequence[
i ].name +
']',
42811 ).scale( 1.0 / fps ) );
42815 return new this( name, - 1, tracks );
42819 static findByName( objectOrClipArray, name ) {
42821 let clipArray = objectOrClipArray;
42823 if ( !
Array.isArray( objectOrClipArray ) ) {
42825 const o = objectOrClipArray;
42826 clipArray =
o.geometry &&
o.geometry.animations ||
o.animations;
42830 for ( let
i = 0;
i < clipArray.length;
i ++ ) {
42832 if ( clipArray[
i ].name === name ) {
42834 return clipArray[
i ];
42844 static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) {
42846 const animationToMorphTargets = {};
42850 const pattern = /^([\
w-]*?)([\
d]+)
$/;
42854 for ( let
i = 0, il = morphTargets.length;
i < il;
i ++ ) {
42856 const morphTarget = morphTargets[
i ];
42857 const parts = morphTarget.name.match( pattern );
42859 if ( parts && parts.length > 1 ) {
42861 const name = parts[ 1 ];
42863 let animationMorphTargets = animationToMorphTargets[ name ];
42865 if ( ! animationMorphTargets ) {
42867 animationToMorphTargets[ name ] = animationMorphTargets = [];
42871 animationMorphTargets.push( morphTarget );
42879 for (
const name in animationToMorphTargets ) {
42881 clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) );
42890 static parseAnimation( animation, bones ) {
42892 if ( ! animation ) {
42894 console.error(
'THREE.AnimationClip: No animation in JSONLoader data.' );
42899 const addNonemptyTrack =
function ( trackType, trackName, animationKeys, propertyName, destTracks ) {
42902 if ( animationKeys.length !== 0 ) {
42907 flattenJSON( animationKeys, times, values, propertyName );
42910 if ( times.length !== 0 ) {
42912 destTracks.push(
new trackType( trackName, times, values ) );
42922 const clipName = animation.name ||
'default';
42923 const fps = animation.fps || 30;
42924 const blendMode = animation.blendMode;
42927 let duration = animation.length || - 1;
42929 const hierarchyTracks = animation.hierarchy || [];
42931 for ( let
h = 0;
h < hierarchyTracks.length;
h ++ ) {
42933 const animationKeys = hierarchyTracks[
h ].keys;
42936 if ( ! animationKeys || animationKeys.length === 0 )
continue;
42939 if ( animationKeys[ 0 ].morphTargets ) {
42942 const morphTargetNames = {};
42946 for (
k = 0;
k < animationKeys.length;
k ++ ) {
42948 if ( animationKeys[
k ].morphTargets ) {
42950 for ( let
m = 0;
m < animationKeys[
k ].morphTargets.length;
m ++ ) {
42952 morphTargetNames[ animationKeys[
k ].morphTargets[
m ] ] = - 1;
42963 for (
const morphTargetName in morphTargetNames ) {
42968 for ( let
m = 0;
m !== animationKeys[
k ].morphTargets.length; ++
m ) {
42970 const animationKey = animationKeys[
k ];
42972 times.push( animationKey.time );
42973 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 );
42977 tracks.push(
new NumberKeyframeTrack(
'.morphTargetInfluence[' + morphTargetName +
']', times, values ) );
42981 duration = morphTargetNames.length * fps;
42987 const boneName =
'.bones[' + bones[
h ].name +
']';
42990 VectorKeyframeTrack, boneName +
'.position',
42991 animationKeys,
'pos', tracks );
42994 QuaternionKeyframeTrack, boneName +
'.quaternion',
42995 animationKeys,
'rot', tracks );
42998 VectorKeyframeTrack, boneName +
'.scale',
42999 animationKeys,
'scl', tracks );
43005 if ( tracks.length === 0 ) {
43011 const clip =
new this( clipName, duration, tracks, blendMode );
43019 const tracks = this.tracks;
43022 for ( let
i = 0,
n = tracks.length;
i !==
n; ++
i ) {
43024 const track = this.tracks[
i ];
43026 duration =
Math.max( duration, track.times[ track.times.length - 1 ] );
43030 this.duration = duration;
43038 for ( let
i = 0;
i < this.tracks.length;
i ++ ) {
43040 this.tracks[
i ].trim( 0, this.duration );
43052 for ( let
i = 0;
i < this.tracks.length;
i ++ ) {
43054 valid = valid && this.tracks[
i ].validate();
43064 for ( let
i = 0;
i < this.tracks.length;
i ++ ) {
43066 this.tracks[
i ].optimize();
43078 for ( let
i = 0;
i < this.tracks.length;
i ++ ) {
43080 tracks.push( this.tracks[
i ].
clone() );
43084 return new this.constructor( this.name, this.duration, tracks, this.blendMode );
43090 return this.constructor.toJSON(
this );
43096 function getTrackTypeForValueTypeName( typeName ) {
43098 switch ( typeName.toLowerCase() ) {
43106 return NumberKeyframeTrack;
43113 return VectorKeyframeTrack;
43117 return ColorKeyframeTrack;
43121 return QuaternionKeyframeTrack;
43126 return BooleanKeyframeTrack;
43130 return StringKeyframeTrack;
43134 throw new Error(
'THREE.KeyframeTrack: Unsupported typeName: ' + typeName );
43138 function parseKeyframeTrack( json ) {
43142 throw new Error(
'THREE.KeyframeTrack: track type undefined, can not parse' );
43146 const trackType = getTrackTypeForValueTypeName( json.type );
43150 const times = [], values = [];
43152 flattenJSON( json.keys, times, values,
'value' );
43154 json.times = times;
43155 json.values = values;
43162 return trackType.parse( json );
43167 return new trackType( json.name, json.times, json.values, json.interpolation );
43179 add:
function ( key, file ) {
43181 if ( this.enabled ===
false )
return;
43185 this.files[ key ] = file;
43189 get:
function ( key ) {
43191 if ( this.enabled ===
false )
return;
43195 return this.files[ key ];
43199 remove:
function ( key ) {
43201 delete this.files[ key ];
43205 clear:
function () {
43215 constructor( onLoad, onProgress, onError ) {
43217 const scope =
this;
43219 let isLoading =
false;
43220 let itemsLoaded = 0;
43221 let itemsTotal = 0;
43223 const handlers = [];
43229 this.onLoad = onLoad;
43230 this.onProgress = onProgress;
43231 this.onError = onError;
43233 this.itemStart =
function ( url ) {
43237 if ( isLoading ===
false ) {
43241 scope.onStart( url, itemsLoaded, itemsTotal );
43251 this.itemEnd =
function ( url ) {
43255 if ( scope.onProgress !==
undefined ) {
43257 scope.onProgress( url, itemsLoaded, itemsTotal );
43261 if ( itemsLoaded === itemsTotal ) {
43275 this.itemError =
function ( url ) {
43279 scope.onError( url );
43285 this.resolveURL =
function ( url ) {
43287 if ( urlModifier ) {
43289 return urlModifier( url );
43297 this.setURLModifier =
function (
transform ) {
43305 this.addHandler =
function ( regex, loader ) {
43307 handlers.push( regex, loader );
43313 this.removeHandler =
function ( regex ) {
43315 const index = handlers.indexOf( regex );
43317 if ( index !== - 1 ) {
43319 handlers.splice( index, 2 );
43327 this.getHandler =
function ( file ) {
43329 for ( let
i = 0,
l = handlers.length;
i <
l;
i += 2 ) {
43331 const regex = handlers[
i ];
43332 const loader = handlers[
i + 1 ];
43334 if ( regex.global ) regex.lastIndex = 0;
43336 if ( regex.test( file ) ) {
43356 constructor( manager ) {
43360 this.crossOrigin =
'anonymous';
43361 this.withCredentials =
false;
43363 this.resourcePath =
'';
43364 this.requestHeader = {};
43370 loadAsync( url, onProgress ) {
43372 const scope =
this;
43374 return new Promise(
function ( resolve, reject ) {
43376 scope.load( url, resolve, onProgress, reject );
43384 setCrossOrigin( crossOrigin ) {
43386 this.crossOrigin = crossOrigin;
43391 setWithCredentials( value ) {
43393 this.withCredentials = value;
43405 setResourcePath( resourcePath ) {
43407 this.resourcePath = resourcePath;
43412 setRequestHeader( requestHeader ) {
43414 this.requestHeader = requestHeader;
43421 Loader.DEFAULT_MATERIAL_NAME =
'__DEFAULT';
43423 const loading = {};
43425 class HttpError
extends Error {
43427 constructor( message, response ) {
43430 this.response = response;
43436 class FileLoader
extends Loader {
43438 constructor( manager ) {
43444 load( url, onLoad, onProgress, onError ) {
43448 if ( this.path !==
undefined ) url = this.path + url;
43450 url = this.manager.resolveURL( url );
43452 const cached =
Cache.get( url );
43456 this.manager.itemStart( url );
43458 setTimeout( () => {
43460 if ( onLoad ) onLoad( cached );
43462 this.manager.itemEnd( url );
43474 loading[ url ].push( {
43477 onProgress: onProgress,
43487 loading[ url ] = [];
43489 loading[ url ].push( {
43491 onProgress: onProgress,
43496 const req =
new Request( url, {
43497 headers:
new Headers( this.requestHeader ),
43498 credentials: this.withCredentials ?
'include' :
'same-origin',
43503 const mimeType = this.mimeType;
43504 const responseType = this.responseType;
43508 .then( response => {
43510 if ( response.status === 200 || response.status === 0 ) {
43515 if ( response.status === 0 ) {
43517 console.warn(
'THREE.FileLoader: HTTP Status 0 received.' );
43523 if ( typeof ReadableStream ===
'undefined' || response.body ===
undefined || response.body.getReader ===
undefined ) {
43529 const callbacks = loading[ url ];
43530 const reader = response.body.getReader();
43534 const contentLength = response.headers.get(
'Content-Length' ) || response.headers.get(
'X-File-Size' );
43535 const total = contentLength ? parseInt( contentLength ) : 0;
43536 const lengthComputable = total !== 0;
43540 const stream =
new ReadableStream( {
43541 start( controller ) {
43545 function readData() {
43547 reader.read().then( ( { done, value } ) => {
43551 controller.close();
43555 loaded += value.byteLength;
43557 const event =
new ProgressEvent(
'progress', { lengthComputable, loaded, total } );
43558 for ( let
i = 0, il = callbacks.length;
i < il;
i ++ ) {
43560 const callback = callbacks[
i ];
43561 if ( callback.onProgress ) callback.onProgress( event );
43565 controller.enqueue( value );
43582 throw new HttpError( `fetch
for "${response.url}" responded with
${response.status}:
${response.statusText}`, response );
43587 .then( response => {
43589 switch ( responseType ) {
43591 case 'arraybuffer':
43593 return response.arrayBuffer();
43597 return response.blob();
43601 return response.text()
43604 const parser =
new DOMParser();
43605 return parser.parseFromString( text, mimeType );
43611 return response.json();
43617 return response.text();
43622 const re = /charset=
"?([^;"\
s]*)
"?/i;
43623 const exec = re.exec( mimeType );
43624 const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined;
43625 const decoder = new TextDecoder( label );
43626 return response.arrayBuffer().then( ab => decoder.decode( ab ) );
43635 // Add to cache only on HTTP success, so that we do not cache
43636 // error response bodies as proper responses to requests.
43637 Cache.add( url, data );
43639 const callbacks = loading[ url ];
43640 delete loading[ url ];
43642 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
43644 const callback = callbacks[ i ];
43645 if ( callback.onLoad ) callback.onLoad( data );
43652 // Abort errors and other errors are handled the same
43654 const callbacks = loading[ url ];
43656 if ( callbacks === undefined ) {
43658 // When onLoad was called and url was deleted in `loading`
43659 this.manager.itemError( url );
43664 delete loading[ url ];
43666 for ( let i = 0, il = callbacks.length; i < il; i ++ ) {
43668 const callback = callbacks[ i ];
43669 if ( callback.onError ) callback.onError( err );
43673 this.manager.itemError( url );
43678 this.manager.itemEnd( url );
43682 this.manager.itemStart( url );
43686 setResponseType( value ) {
43688 this.responseType = value;
43693 setMimeType( value ) {
43695 this.mimeType = value;
43702 class AnimationLoader extends Loader {
43704 constructor( manager ) {
43710 load( url, onLoad, onProgress, onError ) {
43712 const scope = this;
43714 const loader = new FileLoader( this.manager );
43715 loader.setPath( this.path );
43716 loader.setRequestHeader( this.requestHeader );
43717 loader.setWithCredentials( this.withCredentials );
43718 loader.load( url, function ( text ) {
43722 onLoad( scope.parse( JSON.parse( text ) ) );
43732 console.error( e );
43736 scope.manager.itemError( url );
43740 }, onProgress, onError );
43746 const animations = [];
43748 for ( let i = 0; i < json.length; i ++ ) {
43750 const clip = AnimationClip.parse( json[ i ] );
43752 animations.push( clip );
43768 class CompressedTextureLoader extends Loader {
43770 constructor( manager ) {
43776 load( url, onLoad, onProgress, onError ) {
43778 const scope = this;
43782 const texture = new CompressedTexture();
43784 const loader = new FileLoader( this.manager );
43785 loader.setPath( this.path );
43786 loader.setResponseType( 'arraybuffer' );
43787 loader.setRequestHeader( this.requestHeader );
43788 loader.setWithCredentials( scope.withCredentials );
43792 function loadTexture( i ) {
43794 loader.load( url[ i ], function ( buffer ) {
43796 const texDatas = scope.parse( buffer, true );
43799 width: texDatas.width,
43800 height: texDatas.height,
43801 format: texDatas.format,
43802 mipmaps: texDatas.mipmaps
43807 if ( loaded === 6 ) {
43809 if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter;
43811 texture.image = images;
43812 texture.format = texDatas.format;
43813 texture.needsUpdate = true;
43815 if ( onLoad ) onLoad( texture );
43819 }, onProgress, onError );
43823 if ( Array.isArray( url ) ) {
43825 for ( let i = 0, il = url.length; i < il; ++ i ) {
43833 // compressed cubemap texture stored in a single DDS file
43835 loader.load( url, function ( buffer ) {
43837 const texDatas = scope.parse( buffer, true );
43839 if ( texDatas.isCubemap ) {
43841 const faces = texDatas.mipmaps.length / texDatas.mipmapCount;
43843 for ( let f = 0; f < faces; f ++ ) {
43845 images[ f ] = { mipmaps: [] };
43847 for ( let i = 0; i < texDatas.mipmapCount; i ++ ) {
43849 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] );
43850 images[ f ].format = texDatas.format;
43851 images[ f ].width = texDatas.width;
43852 images[ f ].height = texDatas.height;
43858 texture.image = images;
43862 texture.image.width = texDatas.width;
43863 texture.image.height = texDatas.height;
43864 texture.mipmaps = texDatas.mipmaps;
43868 if ( texDatas.mipmapCount === 1 ) {
43870 texture.minFilter = LinearFilter;
43874 texture.format = texDatas.format;
43875 texture.needsUpdate = true;
43877 if ( onLoad ) onLoad( texture );
43879 }, onProgress, onError );
43889 class ImageLoader extends Loader {
43891 constructor( manager ) {
43897 load( url, onLoad, onProgress, onError ) {
43899 if ( this.path !== undefined ) url = this.path + url;
43901 url = this.manager.resolveURL( url );
43903 const scope = this;
43905 const cached = Cache.get( url );
43907 if ( cached !== undefined ) {
43909 scope.manager.itemStart( url );
43911 setTimeout( function () {
43913 if ( onLoad ) onLoad( cached );
43915 scope.manager.itemEnd( url );
43923 const image = createElementNS( 'img' );
43925 function onImageLoad() {
43927 removeEventListeners();
43929 Cache.add( url, this );
43931 if ( onLoad ) onLoad( this );
43933 scope.manager.itemEnd( url );
43937 function onImageError( event ) {
43939 removeEventListeners();
43941 if ( onError ) onError( event );
43943 scope.manager.itemError( url );
43944 scope.manager.itemEnd( url );
43948 function removeEventListeners() {
43950 image.removeEventListener( 'load', onImageLoad, false );
43951 image.removeEventListener( 'error', onImageError, false );
43955 image.addEventListener( 'load', onImageLoad, false );
43956 image.addEventListener( 'error', onImageError, false );
43958 if ( url.slice( 0, 5 ) !== 'data:' ) {
43960 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin;
43964 scope.manager.itemStart( url );
43974 class CubeTextureLoader extends Loader {
43976 constructor( manager ) {
43982 load( urls, onLoad, onProgress, onError ) {
43984 const texture = new CubeTexture();
43985 texture.colorSpace = SRGBColorSpace;
43987 const loader = new ImageLoader( this.manager );
43988 loader.setCrossOrigin( this.crossOrigin );
43989 loader.setPath( this.path );
43993 function loadTexture( i ) {
43995 loader.load( urls[ i ], function ( image ) {
43997 texture.images[ i ] = image;
44001 if ( loaded === 6 ) {
44003 texture.needsUpdate = true;
44005 if ( onLoad ) onLoad( texture );
44009 }, undefined, onError );
44013 for ( let i = 0; i < urls.length; ++ i ) {
44031 class DataTextureLoader extends Loader {
44033 constructor( manager ) {
44039 load( url, onLoad, onProgress, onError ) {
44041 const scope = this;
44043 const texture = new DataTexture();
44045 const loader = new FileLoader( this.manager );
44046 loader.setResponseType( 'arraybuffer' );
44047 loader.setRequestHeader( this.requestHeader );
44048 loader.setPath( this.path );
44049 loader.setWithCredentials( scope.withCredentials );
44050 loader.load( url, function ( buffer ) {
44056 texData = scope.parse( buffer );
44058 } catch ( error ) {
44060 if ( onError !== undefined ) {
44066 console.error( error );
44073 if ( texData.image !== undefined ) {
44075 texture.image = texData.image;
44077 } else if ( texData.data !== undefined ) {
44079 texture.image.width = texData.width;
44080 texture.image.height = texData.height;
44081 texture.image.data = texData.data;
44085 texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping;
44086 texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping;
44088 texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter;
44089 texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter;
44091 texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1;
44093 if ( texData.colorSpace !== undefined ) {
44095 texture.colorSpace = texData.colorSpace;
44097 } else if ( texData.encoding !== undefined ) { // @deprecated, r152
44099 texture.encoding = texData.encoding;
44103 if ( texData.flipY !== undefined ) {
44105 texture.flipY = texData.flipY;
44109 if ( texData.format !== undefined ) {
44111 texture.format = texData.format;
44115 if ( texData.type !== undefined ) {
44117 texture.type = texData.type;
44121 if ( texData.mipmaps !== undefined ) {
44123 texture.mipmaps = texData.mipmaps;
44124 texture.minFilter = LinearMipmapLinearFilter; // presumably...
44128 if ( texData.mipmapCount === 1 ) {
44130 texture.minFilter = LinearFilter;
44134 if ( texData.generateMipmaps !== undefined ) {
44136 texture.generateMipmaps = texData.generateMipmaps;
44140 texture.needsUpdate = true;
44142 if ( onLoad ) onLoad( texture, texData );
44144 }, onProgress, onError );
44153 class TextureLoader extends Loader {
44155 constructor( manager ) {
44161 load( url, onLoad, onProgress, onError ) {
44163 const texture = new Texture();
44165 const loader = new ImageLoader( this.manager );
44166 loader.setCrossOrigin( this.crossOrigin );
44167 loader.setPath( this.path );
44169 loader.load( url, function ( image ) {
44171 texture.image = image;
44172 texture.needsUpdate = true;
44174 if ( onLoad !== undefined ) {
44180 }, onProgress, onError );
44188 class Light extends Object3D {
44190 constructor( color, intensity = 1 ) {
44194 this.isLight = true;
44196 this.type = 'Light';
44198 this.color = new Color( color );
44199 this.intensity = intensity;
44205 // Empty here in base class; some subclasses override.
44209 copy( source, recursive ) {
44211 super.copy( source, recursive );
44213 this.color.copy( source.color );
44214 this.intensity = source.intensity;
44222 const data = super.toJSON( meta );
44224 data.object.color = this.color.getHex();
44225 data.object.intensity = this.intensity;
44227 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex();
44229 if ( this.distance !== undefined ) data.object.distance = this.distance;
44230 if ( this.angle !== undefined ) data.object.angle = this.angle;
44231 if ( this.decay !== undefined ) data.object.decay = this.decay;
44232 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra;
44234 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON();
44242 class HemisphereLight extends Light {
44244 constructor( skyColor, groundColor, intensity ) {
44246 super( skyColor, intensity );
44248 this.isHemisphereLight = true;
44250 this.type = 'HemisphereLight';
44252 this.position.copy( Object3D.DEFAULT_UP );
44253 this.updateMatrix();
44255 this.groundColor = new Color( groundColor );
44259 copy( source, recursive ) {
44261 super.copy( source, recursive );
44263 this.groundColor.copy( source.groundColor );
44271 const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4();
44272 const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3();
44273 const _lookTarget$1 = /*@__PURE__*/ new Vector3();
44275 class LightShadow {
44277 constructor( camera ) {
44279 this.camera = camera;
44282 this.normalBias = 0;
44284 this.blurSamples = 8;
44286 this.mapSize = new Vector2( 512, 512 );
44289 this.mapPass = null;
44290 this.matrix = new Matrix4();
44292 this.autoUpdate = true;
44293 this.needsUpdate = false;
44295 this._frustum = new Frustum();
44296 this._frameExtents = new Vector2( 1, 1 );
44298 this._viewportCount = 1;
44300 this._viewports = [
44302 new Vector4( 0, 0, 1, 1 )
44308 getViewportCount() {
44310 return this._viewportCount;
44316 return this._frustum;
44320 updateMatrices( light ) {
44322 const shadowCamera = this.camera;
44323 const shadowMatrix = this.matrix;
44325 _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld );
44326 shadowCamera.position.copy( _lightPositionWorld$1 );
44328 _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld );
44329 shadowCamera.lookAt( _lookTarget$1 );
44330 shadowCamera.updateMatrixWorld();
44332 _projScreenMatrix$1.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
44333 this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 );
44336 0.5, 0.0, 0.0, 0.5,
44337 0.0, 0.5, 0.0, 0.5,
44338 0.0, 0.0, 0.5, 0.5,
44342 shadowMatrix.multiply( _projScreenMatrix$1 );
44346 getViewport( viewportIndex ) {
44348 return this._viewports[ viewportIndex ];
44352 getFrameExtents() {
44354 return this._frameExtents;
44362 this.map.dispose();
44366 if ( this.mapPass ) {
44368 this.mapPass.dispose();
44376 this.camera = source.camera.clone();
44378 this.bias = source.bias;
44379 this.radius = source.radius;
44381 this.mapSize.copy( source.mapSize );
44389 return new this.constructor().copy( this );
44397 if ( this.bias !== 0 ) object.bias = this.bias;
44398 if ( this.normalBias !== 0 ) object.normalBias = this.normalBias;
44399 if ( this.radius !== 1 ) object.radius = this.radius;
44400 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray();
44402 object.camera = this.camera.toJSON( false ).object;
44403 delete object.camera.matrix;
44411 class SpotLightShadow extends LightShadow {
44415 super( new PerspectiveCamera( 50, 1, 0.5, 500 ) );
44417 this.isSpotLightShadow = true;
44423 updateMatrices( light ) {
44425 const camera = this.camera;
44427 const fov = RAD2DEG * 2 * light.angle * this.focus;
44428 const aspect = this.mapSize.width / this.mapSize.height;
44429 const far = light.distance || camera.far;
44431 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
44434 camera.aspect = aspect;
44436 camera.updateProjectionMatrix();
44440 super.updateMatrices( light );
44446 super.copy( source );
44448 this.focus = source.focus;
44456 class SpotLight extends Light {
44458 constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) {
44460 super( color, intensity );
44462 this.isSpotLight = true;
44464 this.type = 'SpotLight';
44466 this.position.copy( Object3D.DEFAULT_UP );
44467 this.updateMatrix();
44469 this.target = new Object3D();
44471 this.distance = distance;
44472 this.angle = angle;
44473 this.penumbra = penumbra;
44474 this.decay = decay;
44478 this.shadow = new SpotLightShadow();
44484 // compute the light's luminous power (in lumens) from its intensity (in candela)
44485 // by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd)
44486 return this.intensity * Math.PI;
44490 set power( power ) {
44492 // set the light's intensity (in candela) from the desired luminous power (in lumens)
44493 this.intensity = power / Math.PI;
44499 this.shadow.dispose();
44503 copy( source, recursive ) {
44505 super.copy( source, recursive );
44507 this.distance = source.distance;
44508 this.angle = source.angle;
44509 this.penumbra = source.penumbra;
44510 this.decay = source.decay;
44512 this.target = source.target.clone();
44514 this.shadow = source.shadow.clone();
44522 const _projScreenMatrix = /*@__PURE__*/ new Matrix4();
44523 const _lightPositionWorld = /*@__PURE__*/ new Vector3();
44524 const _lookTarget = /*@__PURE__*/ new Vector3();
44526 class PointLightShadow extends LightShadow {
44530 super( new PerspectiveCamera( 90, 1, 0.5, 500 ) );
44532 this.isPointLightShadow = true;
44534 this._frameExtents = new Vector2( 4, 2 );
44536 this._viewportCount = 6;
44538 this._viewports = [
44539 // These viewports map a cube-map onto a 2D texture with the
44540 // following orientation:
44545 // X - Positive x direction
44546 // x - Negative x direction
44547 // Y - Positive y direction
44548 // y - Negative y direction
44549 // Z - Positive z direction
44550 // z - Negative z direction
44553 new Vector4( 2, 1, 1, 1 ),
44555 new Vector4( 0, 1, 1, 1 ),
44557 new Vector4( 3, 1, 1, 1 ),
44559 new Vector4( 1, 1, 1, 1 ),
44561 new Vector4( 3, 0, 1, 1 ),
44563 new Vector4( 1, 0, 1, 1 )
44566 this._cubeDirections = [
44567 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
44568 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 )
44572 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ),
44573 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 )
44578 updateMatrices( light, viewportIndex = 0 ) {
44580 const camera = this.camera;
44581 const shadowMatrix = this.matrix;
44583 const far = light.distance || camera.far;
44585 if ( far !== camera.far ) {
44588 camera.updateProjectionMatrix();
44592 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
44593 camera.position.copy( _lightPositionWorld );
44595 _lookTarget.copy( camera.position );
44596 _lookTarget.add( this._cubeDirections[ viewportIndex ] );
44597 camera.up.copy( this._cubeUps[ viewportIndex ] );
44598 camera.lookAt( _lookTarget );
44599 camera.updateMatrixWorld();
44601 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
44603 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
44604 this._frustum.setFromProjectionMatrix( _projScreenMatrix );
44610 class PointLight extends Light {
44612 constructor( color, intensity, distance = 0, decay = 2 ) {
44614 super( color, intensity );
44616 this.isPointLight = true;
44618 this.type = 'PointLight';
44620 this.distance = distance;
44621 this.decay = decay;
44623 this.shadow = new PointLightShadow();
44629 // compute the light's luminous power (in lumens) from its intensity (in candela)
44630 // for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd)
44631 return this.intensity * 4 * Math.PI;
44635 set power( power ) {
44637 // set the light's intensity (in candela) from the desired luminous power (in lumens)
44638 this.intensity = power / ( 4 * Math.PI );
44644 this.shadow.dispose();
44648 copy( source, recursive ) {
44650 super.copy( source, recursive );
44652 this.distance = source.distance;
44653 this.decay = source.decay;
44655 this.shadow = source.shadow.clone();
44663 class DirectionalLightShadow extends LightShadow {
44667 super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) );
44669 this.isDirectionalLightShadow = true;
44675 class DirectionalLight extends Light {
44677 constructor( color, intensity ) {
44679 super( color, intensity );
44681 this.isDirectionalLight = true;
44683 this.type = 'DirectionalLight';
44685 this.position.copy( Object3D.DEFAULT_UP );
44686 this.updateMatrix();
44688 this.target = new Object3D();
44690 this.shadow = new DirectionalLightShadow();
44696 this.shadow.dispose();
44702 super.copy( source );
44704 this.target = source.target.clone();
44705 this.shadow = source.shadow.clone();
44713 class AmbientLight extends Light {
44715 constructor( color, intensity ) {
44717 super( color, intensity );
44719 this.isAmbientLight = true;
44721 this.type = 'AmbientLight';
44727 class RectAreaLight extends Light {
44729 constructor( color, intensity, width = 10, height = 10 ) {
44731 super( color, intensity );
44733 this.isRectAreaLight = true;
44735 this.type = 'RectAreaLight';
44737 this.width = width;
44738 this.height = height;
44744 // compute the light's luminous power (in lumens) from its intensity (in nits)
44745 return this.intensity * this.width * this.height * Math.PI;
44749 set power( power ) {
44751 // set the light's intensity (in nits) from the desired luminous power (in lumens)
44752 this.intensity = power / ( this.width * this.height * Math.PI );
44758 super.copy( source );
44760 this.width = source.width;
44761 this.height = source.height;
44769 const data = super.toJSON( meta );
44771 data.object.width = this.width;
44772 data.object.height = this.height;
44788 // 3-band SH defined by 9 coefficients
44790 class SphericalHarmonics3 {
44794 this.isSphericalHarmonics3 = true;
44796 this.coefficients = [];
44798 for ( let i = 0; i < 9; i ++ ) {
44800 this.coefficients.push( new Vector3() );
44806 set( coefficients ) {
44808 for ( let i = 0; i < 9; i ++ ) {
44810 this.coefficients[ i ].copy( coefficients[ i ] );
44820 for ( let i = 0; i < 9; i ++ ) {
44822 this.coefficients[ i ].set( 0, 0, 0 );
44830 // get the radiance in the direction of the normal
44831 // target is a Vector3
44832 getAt( normal, target ) {
44834 // normal is assumed to be unit length
44836 const x = normal.x, y = normal.y, z = normal.z;
44838 const coeff = this.coefficients;
44841 target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 );
44844 target.addScaledVector( coeff[ 1 ], 0.488603 * y );
44845 target.addScaledVector( coeff[ 2 ], 0.488603 * z );
44846 target.addScaledVector( coeff[ 3 ], 0.488603 * x );
44849 target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) );
44850 target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) );
44851 target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) );
44852 target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) );
44853 target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) );
44859 // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal
44860 // target is a Vector3
44861 // https://graphics.stanford.edu/papers/envmap/envmap.pdf
44862 getIrradianceAt( normal, target ) {
44864 // normal is assumed to be unit length
44866 const x = normal.x, y = normal.y, z = normal.z;
44868 const coeff = this.coefficients;
44871 target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095
44874 target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603
44875 target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z );
44876 target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x );
44879 target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548
44880 target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z );
44881 target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3
44882 target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z );
44883 target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274
44891 for ( let i = 0; i < 9; i ++ ) {
44893 this.coefficients[ i ].add( sh.coefficients[ i ] );
44901 addScaledSH( sh, s ) {
44903 for ( let i = 0; i < 9; i ++ ) {
44905 this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s );
44915 for ( let i = 0; i < 9; i ++ ) {
44917 this.coefficients[ i ].multiplyScalar( s );
44925 lerp( sh, alpha ) {
44927 for ( let i = 0; i < 9; i ++ ) {
44929 this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha );
44939 for ( let i = 0; i < 9; i ++ ) {
44941 if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) {
44955 return this.set( sh.coefficients );
44961 return new this.constructor().copy( this );
44965 fromArray( array, offset = 0 ) {
44967 const coefficients = this.coefficients;
44969 for ( let i = 0; i < 9; i ++ ) {
44971 coefficients[ i ].fromArray( array, offset + ( i * 3 ) );
44979 toArray( array = [], offset = 0 ) {
44981 const coefficients = this.coefficients;
44983 for ( let i = 0; i < 9; i ++ ) {
44985 coefficients[ i ].toArray( array, offset + ( i * 3 ) );
44993 // evaluate the basis functions
44994 // shBasis is an Array[ 9 ]
44995 static getBasisAt( normal, shBasis ) {
44997 // normal is assumed to be unit length
44999 const x = normal.x, y = normal.y, z = normal.z;
45002 shBasis[ 0 ] = 0.282095;
45005 shBasis[ 1 ] = 0.488603 * y;
45006 shBasis[ 2 ] = 0.488603 * z;
45007 shBasis[ 3 ] = 0.488603 * x;
45010 shBasis[ 4 ] = 1.092548 * x * y;
45011 shBasis[ 5 ] = 1.092548 * y * z;
45012 shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 );
45013 shBasis[ 7 ] = 1.092548 * x * z;
45014 shBasis[ 8 ] = 0.546274 * ( x * x - y * y );
45020 class LightProbe extends Light {
45022 constructor( sh = new SphericalHarmonics3(), intensity = 1 ) {
45024 super( undefined, intensity );
45026 this.isLightProbe = true;
45034 super.copy( source );
45036 this.sh.copy( source.sh );
45044 this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON();
45045 this.sh.fromArray( json.sh );
45053 const data = super.toJSON( meta );
45055 data.object.sh = this.sh.toArray();
45063 class MaterialLoader extends Loader {
45065 constructor( manager ) {
45068 this.textures = {};
45072 load( url, onLoad, onProgress, onError ) {
45074 const scope = this;
45076 const loader = new FileLoader( scope.manager );
45077 loader.setPath( scope.path );
45078 loader.setRequestHeader( scope.requestHeader );
45079 loader.setWithCredentials( scope.withCredentials );
45080 loader.load( url, function ( text ) {
45084 onLoad( scope.parse( JSON.parse( text ) ) );
45094 console.error( e );
45098 scope.manager.itemError( url );
45102 }, onProgress, onError );
45108 const textures = this.textures;
45110 function getTexture( name ) {
45112 if ( textures[ name ] === undefined ) {
45114 console.warn( 'THREE.MaterialLoader: Undefined texture', name );
45118 return textures[ name ];
45122 const material = MaterialLoader.createMaterialFromType( json.type );
45124 if ( json.uuid !== undefined ) material.uuid = json.uuid;
45125 if ( json.name !== undefined ) material.name = json.name;
45126 if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color );
45127 if ( json.roughness !== undefined ) material.roughness = json.roughness;
45128 if ( json.metalness !== undefined ) material.metalness = json.metalness;
45129 if ( json.sheen !== undefined ) material.sheen = json.sheen;
45130 if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor );
45131 if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness;
45132 if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive );
45133 if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular );
45134 if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity;
45135 if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor );
45136 if ( json.shininess !== undefined ) material.shininess = json.shininess;
45137 if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat;
45138 if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness;
45139 if ( json.iridescence !== undefined ) material.iridescence = json.iridescence;
45140 if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR;
45141 if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange;
45142 if ( json.transmission !== undefined ) material.transmission = json.transmission;
45143 if ( json.thickness !== undefined ) material.thickness = json.thickness;
45144 if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance;
45145 if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor );
45146 if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy;
45147 if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation;
45148 if ( json.fog !== undefined ) material.fog = json.fog;
45149 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading;
45150 if ( json.blending !== undefined ) material.blending = json.blending;
45151 if ( json.combine !== undefined ) material.combine = json.combine;
45152 if ( json.side !== undefined ) material.side = json.side;
45153 if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide;
45154 if ( json.opacity !== undefined ) material.opacity = json.opacity;
45155 if ( json.transparent !== undefined ) material.transparent = json.transparent;
45156 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest;
45157 if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash;
45158 if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc;
45159 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
45160 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
45161 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
45162 if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc;
45163 if ( json.blendDst !== undefined ) material.blendDst = json.blendDst;
45164 if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation;
45165 if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha;
45166 if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha;
45167 if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha;
45168 if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor );
45169 if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha;
45170 if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
45171 if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
45172 if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
45173 if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
45174 if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
45175 if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
45176 if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
45177 if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
45179 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
45180 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
45181 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
45182 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
45184 if ( json.rotation !== undefined ) material.rotation = json.rotation;
45186 if ( json.linewidth !== undefined ) material.linewidth = json.linewidth;
45187 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize;
45188 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize;
45189 if ( json.scale !== undefined ) material.scale = json.scale;
45191 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset;
45192 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor;
45193 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits;
45195 if ( json.dithering !== undefined ) material.dithering = json.dithering;
45197 if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage;
45198 if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha;
45199 if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass;
45201 if ( json.visible !== undefined ) material.visible = json.visible;
45203 if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped;
45205 if ( json.userData !== undefined ) material.userData = json.userData;
45207 if ( json.vertexColors !== undefined ) {
45209 if ( typeof json.vertexColors === 'number' ) {
45211 material.vertexColors = ( json.vertexColors > 0 ) ? true : false;
45215 material.vertexColors = json.vertexColors;
45223 if ( json.uniforms !== undefined ) {
45225 for ( const name in json.uniforms ) {
45227 const uniform = json.uniforms[ name ];
45229 material.uniforms[ name ] = {};
45231 switch ( uniform.type ) {
45234 material.uniforms[ name ].value = getTexture( uniform.value );
45238 material.uniforms[ name ].value = new Color().setHex( uniform.value );
45242 material.uniforms[ name ].value = new Vector2().fromArray( uniform.value );
45246 material.uniforms[ name ].value = new Vector3().fromArray( uniform.value );
45250 material.uniforms[ name ].value = new Vector4().fromArray( uniform.value );
45254 material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value );
45258 material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value );
45262 material.uniforms[ name ].value = uniform.value;
45270 if ( json.defines !== undefined ) material.defines = json.defines;
45271 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader;
45272 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader;
45273 if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion;
45275 if ( json.extensions !== undefined ) {
45277 for ( const key in json.extensions ) {
45279 material.extensions[ key ] = json.extensions[ key ];
45285 if ( json.lights !== undefined ) material.lights = json.lights;
45286 if ( json.clipping !== undefined ) material.clipping = json.clipping;
45288 // for PointsMaterial
45290 if ( json.size !== undefined ) material.size = json.size;
45291 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation;
45295 if ( json.map !== undefined ) material.map = getTexture( json.map );
45296 if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap );
45298 if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap );
45300 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap );
45301 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale;
45303 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap );
45304 if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType;
45305 if ( json.normalScale !== undefined ) {
45307 let normalScale = json.normalScale;
45309 if ( Array.isArray( normalScale ) === false ) {
45311 // Blender exporter used to export a scalar. See #7459
45313 normalScale = [ normalScale, normalScale ];
45317 material.normalScale = new Vector2().fromArray( normalScale );
45321 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap );
45322 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale;
45323 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias;
45325 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap );
45326 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap );
45328 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap );
45329 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity;
45331 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap );
45332 if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap );
45333 if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap );
45335 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap );
45336 if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity;
45338 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity;
45339 if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio;
45341 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap );
45342 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity;
45344 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap );
45345 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity;
45347 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap );
45349 if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap );
45350 if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap );
45351 if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap );
45352 if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale );
45354 if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap );
45355 if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap );
45357 if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap );
45358 if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap );
45360 if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap );
45362 if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap );
45363 if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap );
45369 setTextures( value ) {
45371 this.textures = value;
45376 static createMaterialFromType( type ) {
45378 const materialLib = {
45384 MeshPhysicalMaterial,
45385 MeshStandardMaterial,
45388 MeshNormalMaterial,
45389 MeshLambertMaterial,
45391 MeshDistanceMaterial,
45393 MeshMatcapMaterial,
45394 LineDashedMaterial,
45399 return new materialLib[ type ]();
45405 class LoaderUtils {
45407 static decodeText( array ) {
45409 if ( typeof TextDecoder !== 'undefined' ) {
45411 return new TextDecoder().decode( array );
45415 // Avoid the String.fromCharCode.apply(null, array) shortcut, which
45416 // throws a "maximum call stack size exceeded
" error for large arrays.
45420 for ( let i = 0, il = array.length; i < il; i ++ ) {
45422 // Implicitly assumes little-endian.
45423 s += String.fromCharCode( array[ i ] );
45429 // merges multi-byte utf-8 characters.
45431 return decodeURIComponent( escape( s ) );
45433 } catch ( e ) { // see #16358
45441 static extractUrlBase( url ) {
45443 const index = url.lastIndexOf( '/' );
45445 if ( index === - 1 ) return './';
45447 return url.slice( 0, index + 1 );
45451 static resolveURL( url, path ) {
45454 if ( typeof url !== 'string' || url === '' ) return '';
45456 // Host Relative URL
45457 if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {
45459 path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' );
45463 // Absolute URL http://,https://,//
45464 if ( /^(https?:)?\/\//i.test( url ) ) return url;
45467 if ( /^data:.*,.*$/i.test( url ) ) return url;
45470 if ( /^blob:.*$/i.test( url ) ) return url;
45479 class InstancedBufferGeometry extends BufferGeometry {
45485 this.isInstancedBufferGeometry = true;
45487 this.type = 'InstancedBufferGeometry';
45488 this.instanceCount = Infinity;
45494 super.copy( source );
45496 this.instanceCount = source.instanceCount;
45504 const data = super.toJSON();
45506 data.instanceCount = this.instanceCount;
45508 data.isInstancedBufferGeometry = true;
45516 class BufferGeometryLoader extends Loader {
45518 constructor( manager ) {
45524 load( url, onLoad, onProgress, onError ) {
45526 const scope = this;
45528 const loader = new FileLoader( scope.manager );
45529 loader.setPath( scope.path );
45530 loader.setRequestHeader( scope.requestHeader );
45531 loader.setWithCredentials( scope.withCredentials );
45532 loader.load( url, function ( text ) {
45536 onLoad( scope.parse( JSON.parse( text ) ) );
45546 console.error( e );
45550 scope.manager.itemError( url );
45554 }, onProgress, onError );
45560 const interleavedBufferMap = {};
45561 const arrayBufferMap = {};
45563 function getInterleavedBuffer( json, uuid ) {
45565 if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ];
45567 const interleavedBuffers = json.interleavedBuffers;
45568 const interleavedBuffer = interleavedBuffers[ uuid ];
45570 const buffer = getArrayBuffer( json, interleavedBuffer.buffer );
45572 const array = getTypedArray( interleavedBuffer.type, buffer );
45573 const ib = new InterleavedBuffer( array, interleavedBuffer.stride );
45574 ib.uuid = interleavedBuffer.uuid;
45576 interleavedBufferMap[ uuid ] = ib;
45582 function getArrayBuffer( json, uuid ) {
45584 if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ];
45586 const arrayBuffers = json.arrayBuffers;
45587 const arrayBuffer = arrayBuffers[ uuid ];
45589 const ab = new Uint32Array( arrayBuffer ).buffer;
45591 arrayBufferMap[ uuid ] = ab;
45597 const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry();
45599 const index = json.data.index;
45601 if ( index !== undefined ) {
45603 const typedArray = getTypedArray( index.type, index.array );
45604 geometry.setIndex( new BufferAttribute( typedArray, 1 ) );
45608 const attributes = json.data.attributes;
45610 for ( const key in attributes ) {
45612 const attribute = attributes[ key ];
45613 let bufferAttribute;
45615 if ( attribute.isInterleavedBufferAttribute ) {
45617 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
45618 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
45622 const typedArray = getTypedArray( attribute.type, attribute.array );
45623 const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute;
45624 bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized );
45628 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
45629 if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage );
45631 geometry.setAttribute( key, bufferAttribute );
45635 const morphAttributes = json.data.morphAttributes;
45637 if ( morphAttributes ) {
45639 for ( const key in morphAttributes ) {
45641 const attributeArray = morphAttributes[ key ];
45645 for ( let i = 0, il = attributeArray.length; i < il; i ++ ) {
45647 const attribute = attributeArray[ i ];
45648 let bufferAttribute;
45650 if ( attribute.isInterleavedBufferAttribute ) {
45652 const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data );
45653 bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized );
45657 const typedArray = getTypedArray( attribute.type, attribute.array );
45658 bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized );
45662 if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name;
45663 array.push( bufferAttribute );
45667 geometry.morphAttributes[ key ] = array;
45673 const morphTargetsRelative = json.data.morphTargetsRelative;
45675 if ( morphTargetsRelative ) {
45677 geometry.morphTargetsRelative = true;
45681 const groups = json.data.groups || json.data.drawcalls || json.data.offsets;
45683 if ( groups !== undefined ) {
45685 for ( let i = 0, n = groups.length; i !== n; ++ i ) {
45687 const group = groups[ i ];
45689 geometry.addGroup( group.start, group.count, group.materialIndex );
45695 const boundingSphere = json.data.boundingSphere;
45697 if ( boundingSphere !== undefined ) {
45699 const center = new Vector3();
45701 if ( boundingSphere.center !== undefined ) {
45703 center.fromArray( boundingSphere.center );
45707 geometry.boundingSphere = new Sphere( center, boundingSphere.radius );
45711 if ( json.name ) geometry.name = json.name;
45712 if ( json.userData ) geometry.userData = json.userData;
45720 class ObjectLoader extends Loader {
45722 constructor( manager ) {
45728 load( url, onLoad, onProgress, onError ) {
45730 const scope = this;
45732 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
45733 this.resourcePath = this.resourcePath || path;
45735 const loader = new FileLoader( this.manager );
45736 loader.setPath( this.path );
45737 loader.setRequestHeader( this.requestHeader );
45738 loader.setWithCredentials( this.withCredentials );
45739 loader.load( url, function ( text ) {
45745 json = JSON.parse( text );
45747 } catch ( error ) {
45749 if ( onError !== undefined ) onError( error );
45751 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message );
45757 const metadata = json.metadata;
45759 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
45761 if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) );
45763 console.error( 'THREE.ObjectLoader: Can\'t load ' + url );
45768 scope.parse( json, onLoad );
45770 }, onProgress, onError );
45774 async loadAsync( url, onProgress ) {
45776 const scope = this;
45778 const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path;
45779 this.resourcePath = this.resourcePath || path;
45781 const loader = new FileLoader( this.manager );
45782 loader.setPath( this.path );
45783 loader.setRequestHeader( this.requestHeader );
45784 loader.setWithCredentials( this.withCredentials );
45786 const text = await loader.loadAsync( url, onProgress );
45788 const json = JSON.parse( text );
45790 const metadata = json.metadata;
45792 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) {
45794 throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url );
45798 return await scope.parseAsync( json );
45802 parse( json, onLoad ) {
45804 const animations = this.parseAnimations( json.animations );
45805 const shapes = this.parseShapes( json.shapes );
45806 const geometries = this.parseGeometries( json.geometries, shapes );
45808 const images = this.parseImages( json.images, function () {
45810 if ( onLoad !== undefined ) onLoad( object );
45814 const textures = this.parseTextures( json.textures, images );
45815 const materials = this.parseMaterials( json.materials, textures );
45817 const object = this.parseObject( json.object, geometries, materials, textures, animations );
45818 const skeletons = this.parseSkeletons( json.skeletons, object );
45820 this.bindSkeletons( object, skeletons );
45824 if ( onLoad !== undefined ) {
45826 let hasImages = false;
45828 for ( const uuid in images ) {
45830 if ( images[ uuid ].data instanceof HTMLImageElement ) {
45839 if ( hasImages === false ) onLoad( object );
45847 async parseAsync( json ) {
45849 const animations = this.parseAnimations( json.animations );
45850 const shapes = this.parseShapes( json.shapes );
45851 const geometries = this.parseGeometries( json.geometries, shapes );
45853 const images = await this.parseImagesAsync( json.images );
45855 const textures = this.parseTextures( json.textures, images );
45856 const materials = this.parseMaterials( json.materials, textures );
45858 const object = this.parseObject( json.object, geometries, materials, textures, animations );
45859 const skeletons = this.parseSkeletons( json.skeletons, object );
45861 this.bindSkeletons( object, skeletons );
45867 parseShapes( json ) {
45871 if ( json !== undefined ) {
45873 for ( let i = 0, l = json.length; i < l; i ++ ) {
45875 const shape = new Shape().fromJSON( json[ i ] );
45877 shapes[ shape.uuid ] = shape;
45887 parseSkeletons( json, object ) {
45889 const skeletons = {};
45892 // generate bone lookup table
45894 object.traverse( function ( child ) {
45896 if ( child.isBone ) bones[ child.uuid ] = child;
45900 // create skeletons
45902 if ( json !== undefined ) {
45904 for ( let i = 0, l = json.length; i < l; i ++ ) {
45906 const skeleton = new Skeleton().fromJSON( json[ i ], bones );
45908 skeletons[ skeleton.uuid ] = skeleton;
45918 parseGeometries( json, shapes ) {
45920 const geometries = {};
45922 if ( json !== undefined ) {
45924 const bufferGeometryLoader = new BufferGeometryLoader();
45926 for ( let i = 0, l = json.length; i < l; i ++ ) {
45929 const data = json[ i ];
45931 switch ( data.type ) {
45933 case 'BufferGeometry':
45934 case 'InstancedBufferGeometry':
45936 geometry = bufferGeometryLoader.parse( data );
45941 if ( data.type in Geometries ) {
45943 geometry = Geometries[ data.type ].fromJSON( data, shapes );
45947 console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }
"` );
45953 geometry.uuid = data.uuid;
45955 if ( data.name !== undefined ) geometry.name = data.name;
45956 if ( data.userData !== undefined ) geometry.userData = data.userData;
45958 geometries[ data.uuid ] = geometry;
45968 parseMaterials( json, textures ) {
45970 const cache = {}; // MultiMaterial
45971 const materials = {};
45973 if ( json !== undefined ) {
45975 const loader = new MaterialLoader();
45976 loader.setTextures( textures );
45978 for ( let i = 0, l = json.length; i < l; i ++ ) {
45980 const data = json[ i ];
45982 if ( cache[ data.uuid ] === undefined ) {
45984 cache[ data.uuid ] = loader.parse( data );
45988 materials[ data.uuid ] = cache[ data.uuid ];
45998 parseAnimations( json ) {
46000 const animations = {};
46002 if ( json !== undefined ) {
46004 for ( let i = 0; i < json.length; i ++ ) {
46006 const data = json[ i ];
46008 const clip = AnimationClip.parse( data );
46010 animations[ clip.uuid ] = clip;
46020 parseImages( json, onLoad ) {
46022 const scope = this;
46027 function loadImage( url ) {
46029 scope.manager.itemStart( url );
46031 return loader.load( url, function () {
46033 scope.manager.itemEnd( url );
46035 }, undefined, function () {
46037 scope.manager.itemError( url );
46038 scope.manager.itemEnd( url );
46044 function deserializeImage( image ) {
46046 if ( typeof image === 'string' ) {
46050 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
46052 return loadImage( path );
46056 if ( image.data ) {
46059 data: getTypedArray( image.type, image.data ),
46060 width: image.width,
46061 height: image.height
46074 if ( json !== undefined && json.length > 0 ) {
46076 const manager = new LoadingManager( onLoad );
46078 loader = new ImageLoader( manager );
46079 loader.setCrossOrigin( this.crossOrigin );
46081 for ( let i = 0, il = json.length; i < il; i ++ ) {
46083 const image = json[ i ];
46084 const url = image.url;
46086 if ( Array.isArray( url ) ) {
46088 // load array of images e.g CubeTexture
46090 const imageArray = [];
46092 for ( let j = 0, jl = url.length; j < jl; j ++ ) {
46094 const currentUrl = url[ j ];
46096 const deserializedImage = deserializeImage( currentUrl );
46098 if ( deserializedImage !== null ) {
46100 if ( deserializedImage instanceof HTMLImageElement ) {
46102 imageArray.push( deserializedImage );
46106 // special case: handle array of data textures for cube textures
46108 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
46116 images[ image.uuid ] = new Source( imageArray );
46120 // load single image
46122 const deserializedImage = deserializeImage( image.url );
46123 images[ image.uuid ] = new Source( deserializedImage );
46136 async parseImagesAsync( json ) {
46138 const scope = this;
46143 async function deserializeImage( image ) {
46145 if ( typeof image === 'string' ) {
46149 const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url;
46151 return await loader.loadAsync( path );
46155 if ( image.data ) {
46158 data: getTypedArray( image.type, image.data ),
46159 width: image.width,
46160 height: image.height
46173 if ( json !== undefined && json.length > 0 ) {
46175 loader = new ImageLoader( this.manager );
46176 loader.setCrossOrigin( this.crossOrigin );
46178 for ( let i = 0, il = json.length; i < il; i ++ ) {
46180 const image = json[ i ];
46181 const url = image.url;
46183 if ( Array.isArray( url ) ) {
46185 // load array of images e.g CubeTexture
46187 const imageArray = [];
46189 for ( let j = 0, jl = url.length; j < jl; j ++ ) {
46191 const currentUrl = url[ j ];
46193 const deserializedImage = await deserializeImage( currentUrl );
46195 if ( deserializedImage !== null ) {
46197 if ( deserializedImage instanceof HTMLImageElement ) {
46199 imageArray.push( deserializedImage );
46203 // special case: handle array of data textures for cube textures
46205 imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) );
46213 images[ image.uuid ] = new Source( imageArray );
46217 // load single image
46219 const deserializedImage = await deserializeImage( image.url );
46220 images[ image.uuid ] = new Source( deserializedImage );
46232 parseTextures( json, images ) {
46234 function parseConstant( value, type ) {
46236 if ( typeof value === 'number' ) return value;
46238 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value );
46240 return type[ value ];
46244 const textures = {};
46246 if ( json !== undefined ) {
46248 for ( let i = 0, l = json.length; i < l; i ++ ) {
46250 const data = json[ i ];
46252 if ( data.image === undefined ) {
46254 console.warn( 'THREE.ObjectLoader: No "image
" specified for', data.uuid );
46258 if ( images[ data.image ] === undefined ) {
46260 console.warn( 'THREE.ObjectLoader: Undefined image', data.image );
46264 const source = images[ data.image ];
46265 const image = source.data;
46269 if ( Array.isArray( image ) ) {
46271 texture = new CubeTexture();
46273 if ( image.length === 6 ) texture.needsUpdate = true;
46277 if ( image && image.data ) {
46279 texture = new DataTexture();
46283 texture = new Texture();
46287 if ( image ) texture.needsUpdate = true; // textures can have undefined image data
46291 texture.source = source;
46293 texture.uuid = data.uuid;
46295 if ( data.name !== undefined ) texture.name = data.name;
46297 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING );
46298 if ( data.channel !== undefined ) texture.channel = data.channel;
46300 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset );
46301 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat );
46302 if ( data.center !== undefined ) texture.center.fromArray( data.center );
46303 if ( data.rotation !== undefined ) texture.rotation = data.rotation;
46305 if ( data.wrap !== undefined ) {
46307 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING );
46308 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING );
46312 if ( data.format !== undefined ) texture.format = data.format;
46313 if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat;
46314 if ( data.type !== undefined ) texture.type = data.type;
46315 if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace;
46316 if ( data.encoding !== undefined ) texture.encoding = data.encoding; // @deprecated, r152
46318 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER );
46319 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER );
46320 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy;
46322 if ( data.flipY !== undefined ) texture.flipY = data.flipY;
46324 if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps;
46325 if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha;
46326 if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment;
46327 if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction;
46329 if ( data.userData !== undefined ) texture.userData = data.userData;
46331 textures[ data.uuid ] = texture;
46341 parseObject( data, geometries, materials, textures, animations ) {
46345 function getGeometry( name ) {
46347 if ( geometries[ name ] === undefined ) {
46349 console.warn( 'THREE.ObjectLoader: Undefined geometry', name );
46353 return geometries[ name ];
46357 function getMaterial( name ) {
46359 if ( name === undefined ) return undefined;
46361 if ( Array.isArray( name ) ) {
46365 for ( let i = 0, l = name.length; i < l; i ++ ) {
46367 const uuid = name[ i ];
46369 if ( materials[ uuid ] === undefined ) {
46371 console.warn( 'THREE.ObjectLoader: Undefined material', uuid );
46375 array.push( materials[ uuid ] );
46383 if ( materials[ name ] === undefined ) {
46385 console.warn( 'THREE.ObjectLoader: Undefined material', name );
46389 return materials[ name ];
46393 function getTexture( uuid ) {
46395 if ( textures[ uuid ] === undefined ) {
46397 console.warn( 'THREE.ObjectLoader: Undefined texture', uuid );
46401 return textures[ uuid ];
46405 let geometry, material;
46407 switch ( data.type ) {
46411 object = new Scene();
46413 if ( data.background !== undefined ) {
46415 if ( Number.isInteger( data.background ) ) {
46417 object.background = new Color( data.background );
46421 object.background = getTexture( data.background );
46427 if ( data.environment !== undefined ) {
46429 object.environment = getTexture( data.environment );
46433 if ( data.fog !== undefined ) {
46435 if ( data.fog.type === 'Fog' ) {
46437 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far );
46439 } else if ( data.fog.type === 'FogExp2' ) {
46441 object.fog = new FogExp2( data.fog.color, data.fog.density );
46445 if ( data.fog.name !== '' ) {
46447 object.fog.name = data.fog.name;
46453 if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness;
46454 if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity;
46458 case 'PerspectiveCamera':
46460 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far );
46462 if ( data.focus !== undefined ) object.focus = data.focus;
46463 if ( data.zoom !== undefined ) object.zoom = data.zoom;
46464 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge;
46465 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset;
46466 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
46470 case 'OrthographicCamera':
46472 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far );
46474 if ( data.zoom !== undefined ) object.zoom = data.zoom;
46475 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view );
46479 case 'AmbientLight':
46481 object = new AmbientLight( data.color, data.intensity );
46485 case 'DirectionalLight':
46487 object = new DirectionalLight( data.color, data.intensity );
46493 object = new PointLight( data.color, data.intensity, data.distance, data.decay );
46497 case 'RectAreaLight':
46499 object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
46505 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
46509 case 'HemisphereLight':
46511 object = new HemisphereLight( data.color, data.groundColor, data.intensity );
46517 object = new LightProbe().fromJSON( data );
46521 case 'SkinnedMesh':
46523 geometry = getGeometry( data.geometry );
46524 material = getMaterial( data.material );
46526 object = new SkinnedMesh( geometry, material );
46528 if ( data.bindMode !== undefined ) object.bindMode = data.bindMode;
46529 if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix );
46530 if ( data.skeleton !== undefined ) object.skeleton = data.skeleton;
46536 geometry = getGeometry( data.geometry );
46537 material = getMaterial( data.material );
46539 object = new Mesh( geometry, material );
46543 case 'InstancedMesh':
46545 geometry = getGeometry( data.geometry );
46546 material = getMaterial( data.material );
46547 const count = data.count;
46548 const instanceMatrix = data.instanceMatrix;
46549 const instanceColor = data.instanceColor;
46551 object = new InstancedMesh( geometry, material, count );
46552 object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 );
46553 if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize );
46557 case 'BatchedMesh':
46559 geometry = getGeometry( data.geometry );
46560 material = getMaterial( data.material );
46562 object = new BatchedMesh( data.maxGeometryCount, data.maxVertexCount, data.maxIndexCount, material );
46563 object.geometry = geometry;
46564 object.perObjectFrustumCulled = data.perObjectFrustumCulled;
46565 object.sortObjects = data.sortObjects;
46567 object._drawRanges = data.drawRanges;
46568 object._reservedRanges = data.reservedRanges;
46570 object._visibility = data.visibility;
46571 object._active = data.active;
46572 object._bounds = data.bounds.map( bound => {
46574 const box = new Box3();
46575 box.min.fromArray( bound.boxMin );
46576 box.max.fromArray( bound.boxMax );
46578 const sphere = new Sphere();
46579 sphere.radius = bound.sphereRadius;
46580 sphere.center.fromArray( bound.sphereCenter );
46583 boxInitialized: bound.boxInitialized,
46586 sphereInitialized: bound.sphereInitialized,
46592 object._maxGeometryCount = data.maxGeometryCount;
46593 object._maxVertexCount = data.maxVertexCount;
46594 object._maxIndexCount = data.maxIndexCount;
46596 object._geometryInitialized = data.geometryInitialized;
46597 object._geometryCount = data.geometryCount;
46599 object._matricesTexture = getTexture( data.matricesTexture.uuid );
46605 object = new LOD();
46611 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) );
46617 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) );
46621 case 'LineSegments':
46623 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) );
46630 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) );
46636 object = new Sprite( getMaterial( data.material ) );
46642 object = new Group();
46648 object = new Bone();
46654 object = new Object3D();
46658 object.uuid = data.uuid;
46660 if ( data.name !== undefined ) object.name = data.name;
46662 if ( data.matrix !== undefined ) {
46664 object.matrix.fromArray( data.matrix );
46666 if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate;
46667 if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale );
46671 if ( data.position !== undefined ) object.position.fromArray( data.position );
46672 if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation );
46673 if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion );
46674 if ( data.scale !== undefined ) object.scale.fromArray( data.scale );
46678 if ( data.up !== undefined ) object.up.fromArray( data.up );
46680 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow;
46681 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow;
46683 if ( data.shadow ) {
46685 if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias;
46686 if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias;
46687 if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius;
46688 if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize );
46689 if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera );
46693 if ( data.visible !== undefined ) object.visible = data.visible;
46694 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled;
46695 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder;
46696 if ( data.userData !== undefined ) object.userData = data.userData;
46697 if ( data.layers !== undefined ) object.layers.mask = data.layers;
46699 if ( data.children !== undefined ) {
46701 const children = data.children;
46703 for ( let i = 0; i < children.length; i ++ ) {
46705 object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) );
46711 if ( data.animations !== undefined ) {
46713 const objectAnimations = data.animations;
46715 for ( let i = 0; i < objectAnimations.length; i ++ ) {
46717 const uuid = objectAnimations[ i ];
46719 object.animations.push( animations[ uuid ] );
46725 if ( data.type === 'LOD' ) {
46727 if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate;
46729 const levels = data.levels;
46731 for ( let l = 0; l < levels.length; l ++ ) {
46733 const level = levels[ l ];
46734 const child = object.getObjectByProperty( 'uuid', level.object );
46736 if ( child !== undefined ) {
46738 object.addLevel( child, level.distance, level.hysteresis );
46750 bindSkeletons( object, skeletons ) {
46752 if ( Object.keys( skeletons ).length === 0 ) return;
46754 object.traverse( function ( child ) {
46756 if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) {
46758 const skeleton = skeletons[ child.skeleton ];
46760 if ( skeleton === undefined ) {
46762 console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton );
46766 child.bind( skeleton, child.bindMatrix );
46778 const TEXTURE_MAPPING = {
46779 UVMapping: UVMapping,
46780 CubeReflectionMapping: CubeReflectionMapping,
46781 CubeRefractionMapping: CubeRefractionMapping,
46782 EquirectangularReflectionMapping: EquirectangularReflectionMapping,
46783 EquirectangularRefractionMapping: EquirectangularRefractionMapping,
46784 CubeUVReflectionMapping: CubeUVReflectionMapping
46787 const TEXTURE_WRAPPING = {
46788 RepeatWrapping: RepeatWrapping,
46789 ClampToEdgeWrapping: ClampToEdgeWrapping,
46790 MirroredRepeatWrapping: MirroredRepeatWrapping
46793 const TEXTURE_FILTER = {
46794 NearestFilter: NearestFilter,
46795 NearestMipmapNearestFilter: NearestMipmapNearestFilter,
46796 NearestMipmapLinearFilter: NearestMipmapLinearFilter,
46797 LinearFilter: LinearFilter,
46798 LinearMipmapNearestFilter: LinearMipmapNearestFilter,
46799 LinearMipmapLinearFilter: LinearMipmapLinearFilter
46802 class ImageBitmapLoader extends Loader {
46804 constructor( manager ) {
46808 this.isImageBitmapLoader = true;
46810 if ( typeof createImageBitmap === 'undefined' ) {
46812 console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' );
46816 if ( typeof fetch === 'undefined' ) {
46818 console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' );
46822 this.options = { premultiplyAlpha: 'none' };
46826 setOptions( options ) {
46828 this.options = options;
46834 load( url, onLoad, onProgress, onError ) {
46836 if ( url === undefined ) url = '';
46838 if ( this.path !== undefined ) url = this.path + url;
46840 url = this.manager.resolveURL( url );
46842 const scope = this;
46844 const cached = Cache.get( url );
46846 if ( cached !== undefined ) {
46848 scope.manager.itemStart( url );
46850 // If cached is a promise, wait for it to resolve
46851 if ( cached.then ) {
46853 cached.then( imageBitmap => {
46855 if ( onLoad ) onLoad( imageBitmap );
46857 scope.manager.itemEnd( url );
46861 if ( onError ) onError( e );
46868 // If cached is not a promise (i.e., it's already an imageBitmap)
46869 setTimeout( function () {
46871 if ( onLoad ) onLoad( cached );
46873 scope.manager.itemEnd( url );
46881 const fetchOptions = {};
46882 fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include';
46883 fetchOptions.headers = this.requestHeader;
46885 const promise = fetch( url, fetchOptions ).then( function ( res ) {
46889 } ).then( function ( blob ) {
46891 return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) );
46893 } ).then( function ( imageBitmap ) {
46895 Cache.add( url, imageBitmap );
46897 if ( onLoad ) onLoad( imageBitmap );
46899 scope.manager.itemEnd( url );
46901 return imageBitmap;
46903 } ).catch( function ( e ) {
46905 if ( onError ) onError( e );
46907 Cache.remove( url );
46909 scope.manager.itemError( url );
46910 scope.manager.itemEnd( url );
46914 Cache.add( url, promise );
46915 scope.manager.itemStart( url );
46923 class AudioContext {
46925 static getContext() {
46927 if ( _context === undefined ) {
46929 _context = new ( window.AudioContext || window.webkitAudioContext )();
46937 static setContext( value ) {
46945 class AudioLoader extends Loader {
46947 constructor( manager ) {
46953 load( url, onLoad, onProgress, onError ) {
46955 const scope = this;
46957 const loader = new FileLoader( this.manager );
46958 loader.setResponseType( 'arraybuffer' );
46959 loader.setPath( this.path );
46960 loader.setRequestHeader( this.requestHeader );
46961 loader.setWithCredentials( this.withCredentials );
46962 loader.load( url, function ( buffer ) {
46966 // Create a copy of the buffer. The `decodeAudioData` method
46967 // detaches the buffer when complete, preventing reuse.
46968 const bufferCopy = buffer.slice( 0 );
46970 const context = AudioContext.getContext();
46971 context.decodeAudioData( bufferCopy, function ( audioBuffer ) {
46973 onLoad( audioBuffer );
46975 } ).catch( handleError );
46983 }, onProgress, onError );
46985 function handleError( e ) {
46993 console.error( e );
46997 scope.manager.itemError( url );
47005 const _eyeRight = /*@__PURE__*/ new Matrix4();
47006 const _eyeLeft = /*@__PURE__*/ new Matrix4();
47007 const _projectionMatrix = /*@__PURE__*/ new Matrix4();
47009 class StereoCamera {
47013 this.type = 'StereoCamera';
47017 this.eyeSep = 0.064;
47019 this.cameraL = new PerspectiveCamera();
47020 this.cameraL.layers.enable( 1 );
47021 this.cameraL.matrixAutoUpdate = false;
47023 this.cameraR = new PerspectiveCamera();
47024 this.cameraR.layers.enable( 2 );
47025 this.cameraR.matrixAutoUpdate = false;
47041 const cache = this._cache;
47043 const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov ||
47044 cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near ||
47045 cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep;
47047 if ( needsUpdate ) {
47049 cache.focus = camera.focus;
47050 cache.fov = camera.fov;
47051 cache.aspect = camera.aspect * this.aspect;
47052 cache.near = camera.near;
47053 cache.far = camera.far;
47054 cache.zoom = camera.zoom;
47055 cache.eyeSep = this.eyeSep;
47057 // Off-axis stereoscopic effect based on
47058 // http://paulbourke.net/stereographics/stereorender/
47060 _projectionMatrix.copy( camera.projectionMatrix );
47061 const eyeSepHalf = cache.eyeSep / 2;
47062 const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus;
47063 const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom;
47066 // translate xOffset
47068 _eyeLeft.elements[ 12 ] = - eyeSepHalf;
47069 _eyeRight.elements[ 12 ] = eyeSepHalf;
47073 xmin = - ymax * cache.aspect + eyeSepOnProjection;
47074 xmax = ymax * cache.aspect + eyeSepOnProjection;
47076 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
47077 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
47079 this.cameraL.projectionMatrix.copy( _projectionMatrix );
47083 xmin = - ymax * cache.aspect - eyeSepOnProjection;
47084 xmax = ymax * cache.aspect - eyeSepOnProjection;
47086 _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin );
47087 _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
47089 this.cameraR.projectionMatrix.copy( _projectionMatrix );
47093 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft );
47094 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight );
47102 constructor( autoStart = true ) {
47104 this.autoStart = autoStart;
47106 this.startTime = 0;
47108 this.elapsedTime = 0;
47110 this.running = false;
47116 this.startTime = now();
47118 this.oldTime = this.startTime;
47119 this.elapsedTime = 0;
47120 this.running = true;
47126 this.getElapsedTime();
47127 this.running = false;
47128 this.autoStart = false;
47135 return this.elapsedTime;
47143 if ( this.autoStart && ! this.running ) {
47150 if ( this.running ) {
47152 const newTime = now();
47154 diff = ( newTime - this.oldTime ) / 1000;
47155 this.oldTime = newTime;
47157 this.elapsedTime += diff;
47169 return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732
47173 const _position$1 = /*@__PURE__*/ new Vector3();
47174 const _quaternion$1 = /*@__PURE__*/ new Quaternion();
47175 const _scale$1 = /*@__PURE__*/ new Vector3();
47176 const _orientation$1 = /*@__PURE__*/ new Vector3();
47178 class AudioListener extends Object3D {
47184 this.type = 'AudioListener';
47186 this.context = AudioContext.getContext();
47188 this.gain = this.context.createGain();
47189 this.gain.connect( this.context.destination );
47191 this.filter = null;
47193 this.timeDelta = 0;
47197 this._clock = new Clock();
47209 if ( this.filter !== null ) {
47211 this.gain.disconnect( this.filter );
47212 this.filter.disconnect( this.context.destination );
47213 this.gain.connect( this.context.destination );
47214 this.filter = null;
47224 return this.filter;
47228 setFilter( value ) {
47230 if ( this.filter !== null ) {
47232 this.gain.disconnect( this.filter );
47233 this.filter.disconnect( this.context.destination );
47237 this.gain.disconnect( this.context.destination );
47241 this.filter = value;
47242 this.gain.connect( this.filter );
47243 this.filter.connect( this.context.destination );
47249 getMasterVolume() {
47251 return this.gain.gain.value;
47255 setMasterVolume( value ) {
47257 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
47263 updateMatrixWorld( force ) {
47265 super.updateMatrixWorld( force );
47267 const listener = this.context.listener;
47268 const up = this.up;
47270 this.timeDelta = this._clock.getDelta();
47272 this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 );
47274 _orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 );
47276 if ( listener.positionX ) {
47278 // code path for Chrome (see #14393)
47280 const endTime = this.context.currentTime + this.timeDelta;
47282 listener.positionX.linearRampToValueAtTime( _position$1.x, endTime );
47283 listener.positionY.linearRampToValueAtTime( _position$1.y, endTime );
47284 listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime );
47285 listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime );
47286 listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime );
47287 listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime );
47288 listener.upX.linearRampToValueAtTime( up.x, endTime );
47289 listener.upY.linearRampToValueAtTime( up.y, endTime );
47290 listener.upZ.linearRampToValueAtTime( up.z, endTime );
47294 listener.setPosition( _position$1.x, _position$1.y, _position$1.z );
47295 listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z );
47303 class Audio extends Object3D {
47305 constructor( listener ) {
47309 this.type = 'Audio';
47311 this.listener = listener;
47312 this.context = listener.context;
47314 this.gain = this.context.createGain();
47315 this.gain.connect( listener.getInput() );
47317 this.autoplay = false;
47319 this.buffer = null;
47322 this.loopStart = 0;
47325 this.duration = undefined;
47326 this.playbackRate = 1;
47327 this.isPlaying = false;
47328 this.hasPlaybackControl = true;
47329 this.source = null;
47330 this.sourceType = 'empty';
47332 this._startedAt = 0;
47333 this._progress = 0;
47334 this._connected = false;
47346 setNodeSource( audioNode ) {
47348 this.hasPlaybackControl = false;
47349 this.sourceType = 'audioNode';
47350 this.source = audioNode;
47357 setMediaElementSource( mediaElement ) {
47359 this.hasPlaybackControl = false;
47360 this.sourceType = 'mediaNode';
47361 this.source = this.context.createMediaElementSource( mediaElement );
47368 setMediaStreamSource( mediaStream ) {
47370 this.hasPlaybackControl = false;
47371 this.sourceType = 'mediaStreamNode';
47372 this.source = this.context.createMediaStreamSource( mediaStream );
47379 setBuffer( audioBuffer ) {
47381 this.buffer = audioBuffer;
47382 this.sourceType = 'buffer';
47384 if ( this.autoplay ) this.play();
47390 play( delay = 0 ) {
47392 if ( this.isPlaying === true ) {
47394 console.warn( 'THREE.Audio: Audio is already playing.' );
47399 if ( this.hasPlaybackControl === false ) {
47401 console.warn( 'THREE.Audio: this Audio has no playback control.' );
47406 this._startedAt = this.context.currentTime + delay;
47408 const source = this.context.createBufferSource();
47409 source.buffer = this.buffer;
47410 source.loop = this.loop;
47411 source.loopStart = this.loopStart;
47412 source.loopEnd = this.loopEnd;
47413 source.onended = this.onEnded.bind( this );
47414 source.start( this._startedAt, this._progress + this.offset, this.duration );
47416 this.isPlaying = true;
47418 this.source = source;
47420 this.setDetune( this.detune );
47421 this.setPlaybackRate( this.playbackRate );
47423 return this.connect();
47429 if ( this.hasPlaybackControl === false ) {
47431 console.warn( 'THREE.Audio: this Audio has no playback control.' );
47436 if ( this.isPlaying === true ) {
47438 // update current progress
47440 this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate;
47442 if ( this.loop === true ) {
47444 // ensure _progress does not exceed duration with looped audios
47446 this._progress = this._progress % ( this.duration || this.buffer.duration );
47450 this.source.stop();
47451 this.source.onended = null;
47453 this.isPlaying = false;
47463 if ( this.hasPlaybackControl === false ) {
47465 console.warn( 'THREE.Audio: this Audio has no playback control.' );
47470 this._progress = 0;
47472 if ( this.source !== null ) {
47474 this.source.stop();
47475 this.source.onended = null;
47479 this.isPlaying = false;
47487 if ( this.filters.length > 0 ) {
47489 this.source.connect( this.filters[ 0 ] );
47491 for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
47493 this.filters[ i - 1 ].connect( this.filters[ i ] );
47497 this.filters[ this.filters.length - 1 ].connect( this.getOutput() );
47501 this.source.connect( this.getOutput() );
47505 this._connected = true;
47513 if ( this._connected === false ) {
47519 if ( this.filters.length > 0 ) {
47521 this.source.disconnect( this.filters[ 0 ] );
47523 for ( let i = 1, l = this.filters.length; i < l; i ++ ) {
47525 this.filters[ i - 1 ].disconnect( this.filters[ i ] );
47529 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() );
47533 this.source.disconnect( this.getOutput() );
47537 this._connected = false;
47545 return this.filters;
47549 setFilters( value ) {
47551 if ( ! value ) value = [];
47553 if ( this._connected === true ) {
47556 this.filters = value.slice();
47561 this.filters = value.slice();
47569 setDetune( value ) {
47571 this.detune = value;
47573 if ( this.source.detune === undefined ) return; // only set detune when available
47575 if ( this.isPlaying === true ) {
47577 this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 );
47587 return this.detune;
47593 return this.getFilters()[ 0 ];
47597 setFilter( filter ) {
47599 return this.setFilters( filter ? [ filter ] : [] );
47603 setPlaybackRate( value ) {
47605 if ( this.hasPlaybackControl === false ) {
47607 console.warn( 'THREE.Audio: this Audio has no playback control.' );
47612 this.playbackRate = value;
47614 if ( this.isPlaying === true ) {
47616 this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 );
47624 getPlaybackRate() {
47626 return this.playbackRate;
47632 this.isPlaying = false;
47638 if ( this.hasPlaybackControl === false ) {
47640 console.warn( 'THREE.Audio: this Audio has no playback control.' );
47651 if ( this.hasPlaybackControl === false ) {
47653 console.warn( 'THREE.Audio: this Audio has no playback control.' );
47660 if ( this.isPlaying === true ) {
47662 this.source.loop = this.loop;
47670 setLoopStart( value ) {
47672 this.loopStart = value;
47678 setLoopEnd( value ) {
47680 this.loopEnd = value;
47688 return this.gain.gain.value;
47692 setVolume( value ) {
47694 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 );
47702 const _position = /*@__PURE__*/ new Vector3();
47703 const _quaternion = /*@__PURE__*/ new Quaternion();
47704 const _scale = /*@__PURE__*/ new Vector3();
47705 const _orientation = /*@__PURE__*/ new Vector3();
47707 class PositionalAudio extends Audio {
47709 constructor( listener ) {
47713 this.panner = this.context.createPanner();
47714 this.panner.panningModel = 'HRTF';
47715 this.panner.connect( this.gain );
47723 this.panner.connect( this.gain );
47729 super.disconnect();
47731 this.panner.disconnect( this.gain );
47737 return this.panner;
47743 return this.panner.refDistance;
47747 setRefDistance( value ) {
47749 this.panner.refDistance = value;
47755 getRolloffFactor() {
47757 return this.panner.rolloffFactor;
47761 setRolloffFactor( value ) {
47763 this.panner.rolloffFactor = value;
47769 getDistanceModel() {
47771 return this.panner.distanceModel;
47775 setDistanceModel( value ) {
47777 this.panner.distanceModel = value;
47785 return this.panner.maxDistance;
47789 setMaxDistance( value ) {
47791 this.panner.maxDistance = value;
47797 setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) {
47799 this.panner.coneInnerAngle = coneInnerAngle;
47800 this.panner.coneOuterAngle = coneOuterAngle;
47801 this.panner.coneOuterGain = coneOuterGain;
47807 updateMatrixWorld( force ) {
47809 super.updateMatrixWorld( force );
47811 if ( this.hasPlaybackControl === true && this.isPlaying === false ) return;
47813 this.matrixWorld.decompose( _position, _quaternion, _scale );
47815 _orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion );
47817 const panner = this.panner;
47819 if ( panner.positionX ) {
47821 // code path for Chrome and Firefox (see #14393)
47823 const endTime = this.context.currentTime + this.listener.timeDelta;
47825 panner.positionX.linearRampToValueAtTime( _position.x, endTime );
47826 panner.positionY.linearRampToValueAtTime( _position.y, endTime );
47827 panner.positionZ.linearRampToValueAtTime( _position.z, endTime );
47828 panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime );
47829 panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime );
47830 panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime );
47834 panner.setPosition( _position.x, _position.y, _position.z );
47835 panner.setOrientation( _orientation.x, _orientation.y, _orientation.z );
47843 class AudioAnalyser {
47845 constructor( audio, fftSize = 2048 ) {
47847 this.analyser = audio.context.createAnalyser();
47848 this.analyser.fftSize = fftSize;
47850 this.data = new Uint8Array( this.analyser.frequencyBinCount );
47852 audio.getOutput().connect( this.analyser );
47857 getFrequencyData() {
47859 this.analyser.getByteFrequencyData( this.data );
47865 getAverageFrequency() {
47868 const data = this.getFrequencyData();
47870 for ( let i = 0; i < data.length; i ++ ) {
47872 value += data[ i ];
47876 return value / data.length;
47882 class PropertyMixer {
47884 constructor( binding, typeName, valueSize ) {
47886 this.binding = binding;
47887 this.valueSize = valueSize;
47890 mixFunctionAdditive,
47893 // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ]
47895 // interpolators can use .buffer as their .result
47896 // the data then goes to 'incoming'
47898 // 'accu0' and 'accu1' are used frame-interleaved for
47899 // the cumulative result and are compared to detect
47902 // 'orig' stores the original state of the property
47904 // 'add' is used for additive cumulative results
47906 // 'work' is optional and is only present for quaternion types. It is used
47907 // to store intermediate quaternion multiplication results
47909 switch ( typeName ) {
47912 mixFunction = this._slerp;
47913 mixFunctionAdditive = this._slerpAdditive;
47914 setIdentity = this._setAdditiveIdentityQuaternion;
47916 this.buffer = new Float64Array( valueSize * 6 );
47917 this._workIndex = 5;
47922 mixFunction = this._select;
47924 // Use the regular mix function and for additive on these types,
47925 // additive is not relevant for non-numeric types
47926 mixFunctionAdditive = this._select;
47928 setIdentity = this._setAdditiveIdentityOther;
47930 this.buffer = new Array( valueSize * 5 );
47934 mixFunction = this._lerp;
47935 mixFunctionAdditive = this._lerpAdditive;
47936 setIdentity = this._setAdditiveIdentityNumeric;
47938 this.buffer = new Float64Array( valueSize * 5 );
47942 this._mixBufferRegion = mixFunction;
47943 this._mixBufferRegionAdditive = mixFunctionAdditive;
47944 this._setIdentity = setIdentity;
47945 this._origIndex = 3;
47946 this._addIndex = 4;
47948 this.cumulativeWeight = 0;
47949 this.cumulativeWeightAdditive = 0;
47952 this.referenceCount = 0;
47956 // accumulate data in the 'incoming' region into 'accu<i>'
47957 accumulate( accuIndex, weight ) {
47959 // note: happily accumulating nothing when weight = 0, the caller knows
47960 // the weight and shouldn't have made the call in the first place
47962 const buffer = this.buffer,
47963 stride = this.valueSize,
47964 offset = accuIndex * stride + stride;
47966 let currentWeight = this.cumulativeWeight;
47968 if ( currentWeight === 0 ) {
47970 // accuN := incoming * weight
47972 for ( let i = 0; i !== stride; ++ i ) {
47974 buffer[ offset + i ] = buffer[ i ];
47978 currentWeight = weight;
47982 // accuN := accuN + incoming * weight
47984 currentWeight += weight;
47985 const mix = weight / currentWeight;
47986 this._mixBufferRegion( buffer, offset, 0, mix, stride );
47990 this.cumulativeWeight = currentWeight;
47994 // accumulate data in the 'incoming' region into 'add'
47995 accumulateAdditive( weight ) {
47997 const buffer = this.buffer,
47998 stride = this.valueSize,
47999 offset = stride * this._addIndex;
48001 if ( this.cumulativeWeightAdditive === 0 ) {
48005 this._setIdentity();
48009 // add := add + incoming * weight
48011 this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride );
48012 this.cumulativeWeightAdditive += weight;
48016 // apply the state of 'accu<i>' to the binding when accus differ
48017 apply( accuIndex ) {
48019 const stride = this.valueSize,
48020 buffer = this.buffer,
48021 offset = accuIndex * stride + stride,
48023 weight = this.cumulativeWeight,
48024 weightAdditive = this.cumulativeWeightAdditive,
48026 binding = this.binding;
48028 this.cumulativeWeight = 0;
48029 this.cumulativeWeightAdditive = 0;
48031 if ( weight < 1 ) {
48033 // accuN := accuN + original * ( 1 - cumulativeWeight )
48035 const originalValueOffset = stride * this._origIndex;
48037 this._mixBufferRegion(
48038 buffer, offset, originalValueOffset, 1 - weight, stride );
48042 if ( weightAdditive > 0 ) {
48044 // accuN := accuN + additive accuN
48046 this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride );
48050 for ( let i = stride, e = stride + stride; i !== e; ++ i ) {
48052 if ( buffer[ i ] !== buffer[ i + stride ] ) {
48054 // value has changed -> update scene graph
48056 binding.setValue( buffer, offset );
48065 // remember the state of the bound property and copy it to both accus
48066 saveOriginalState() {
48068 const binding = this.binding;
48070 const buffer = this.buffer,
48071 stride = this.valueSize,
48073 originalValueOffset = stride * this._origIndex;
48075 binding.getValue( buffer, originalValueOffset );
48077 // accu[0..1] := orig -- initially detect changes against the original
48078 for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) {
48080 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ];
48084 // Add to identity for additive
48085 this._setIdentity();
48087 this.cumulativeWeight = 0;
48088 this.cumulativeWeightAdditive = 0;
48092 // apply the state previously taken via 'saveOriginalState' to the binding
48093 restoreOriginalState() {
48095 const originalValueOffset = this.valueSize * 3;
48096 this.binding.setValue( this.buffer, originalValueOffset );
48100 _setAdditiveIdentityNumeric() {
48102 const startIndex = this._addIndex * this.valueSize;
48103 const endIndex = startIndex + this.valueSize;
48105 for ( let i = startIndex; i < endIndex; i ++ ) {
48107 this.buffer[ i ] = 0;
48113 _setAdditiveIdentityQuaternion() {
48115 this._setAdditiveIdentityNumeric();
48116 this.buffer[ this._addIndex * this.valueSize + 3 ] = 1;
48120 _setAdditiveIdentityOther() {
48122 const startIndex = this._origIndex * this.valueSize;
48123 const targetIndex = this._addIndex * this.valueSize;
48125 for ( let i = 0; i < this.valueSize; i ++ ) {
48127 this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ];
48136 _select( buffer, dstOffset, srcOffset, t, stride ) {
48140 for ( let i = 0; i !== stride; ++ i ) {
48142 buffer[ dstOffset + i ] = buffer[ srcOffset + i ];
48150 _slerp( buffer, dstOffset, srcOffset, t ) {
48152 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t );
48156 _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
48158 const workOffset = this._workIndex * stride;
48160 // Store result in intermediate buffer offset
48161 Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset );
48163 // Slerp to the intermediate result
48164 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t );
48168 _lerp( buffer, dstOffset, srcOffset, t, stride ) {
48172 for ( let i = 0; i !== stride; ++ i ) {
48174 const j = dstOffset + i;
48176 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t;
48182 _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) {
48184 for ( let i = 0; i !== stride; ++ i ) {
48186 const j = dstOffset + i;
48188 buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t;
48196 // Characters [].:/ are reserved for track binding syntax.
48197 const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/';
48198 const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' );
48200 // Attempts to allow node names from any language. ES5's `\w` regexp matches
48201 // only latin characters, and the unicode \p{L} is not yet supported. So
48202 // instead, we exclude reserved characters and match everything else.
48203 const _wordChar = '[^' + _RESERVED_CHARS_RE + ']';
48204 const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']';
48206 // Parent directories, delimited by '/' or ':'. Currently unused, but must
48207 // be matched to parse the rest of the track name.
48208 const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar );
48210 // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'.
48211 const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot );
48213 // Object on target node, and accessor. May not contain reserved
48214 // characters. Accessor may contain any character except closing bracket.
48215 const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar );
48217 // Property and accessor. May not contain reserved characters. Accessor may
48218 // contain any non-bracket characters.
48219 const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar );
48221 const _trackRe = new RegExp( ''
48230 const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ];
48234 constructor( targetGroup, path, optionalParsedPath ) {
48236 const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path );
48238 this._targetGroup = targetGroup;
48239 this._bindings = targetGroup.subscribe_( path, parsedPath );
48243 getValue( array, offset ) {
48245 this.bind(); // bind all binding
48247 const firstValidIndex = this._targetGroup.nCachedObjects_,
48248 binding = this._bindings[ firstValidIndex ];
48250 // and only call .getValue on the first
48251 if ( binding !== undefined ) binding.getValue( array, offset );
48255 setValue( array, offset ) {
48257 const bindings = this._bindings;
48259 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
48261 bindings[ i ].setValue( array, offset );
48269 const bindings = this._bindings;
48271 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
48273 bindings[ i ].bind();
48281 const bindings = this._bindings;
48283 for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) {
48285 bindings[ i ].unbind();
48293 // Note: This class uses a State pattern on a per-method basis:
48294 // 'bind' sets 'this.getValue' / 'setValue' and shadows the
48295 // prototype version of these methods with one that represents
48296 // the bound state. When the property is not found, the methods
48298 class PropertyBinding {
48300 constructor( rootNode, path, parsedPath ) {
48303 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path );
48305 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName );
48307 this.rootNode = rootNode;
48309 // initial state of these methods that calls 'bind'
48310 this.getValue = this._getValue_unbound;
48311 this.setValue = this._setValue_unbound;
48316 static create( root, path, parsedPath ) {
48318 if ( ! ( root && root.isAnimationObjectGroup ) ) {
48320 return new PropertyBinding( root, path, parsedPath );
48324 return new PropertyBinding.Composite( root, path, parsedPath );
48337 static sanitizeNodeName( name ) {
48339 return name.replace( /\s/g, '_' ).replace( _reservedRe, '' );
48343 static parseTrackName( trackName ) {
48345 const matches = _trackRe.exec( trackName );
48347 if ( matches === null ) {
48349 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName );
48354 // directoryName: matches[ 1 ], // (tschw) currently unused
48355 nodeName: matches[ 2 ],
48356 objectName: matches[ 3 ],
48357 objectIndex: matches[ 4 ],
48358 propertyName: matches[ 5 ], // required
48359 propertyIndex: matches[ 6 ]
48362 const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' );
48364 if ( lastDot !== undefined && lastDot !== - 1 ) {
48366 const objectName = results.nodeName.substring( lastDot + 1 );
48368 // Object names must be checked against an allowlist. Otherwise, there
48369 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but
48370 // 'bar' could be the objectName, or part of a nodeName (which can
48371 // include '.' characters).
48372 if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) {
48374 results.nodeName = results.nodeName.substring( 0, lastDot );
48375 results.objectName = objectName;
48381 if ( results.propertyName === null || results.propertyName.length === 0 ) {
48383 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName );
48391 static findNode( root, nodeName ) {
48393 if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) {
48399 // search into skeleton bones.
48400 if ( root.skeleton ) {
48402 const bone = root.skeleton.getBoneByName( nodeName );
48404 if ( bone !== undefined ) {
48412 // search into node subtree.
48413 if ( root.children ) {
48415 const searchNodeSubtree = function ( children ) {
48417 for ( let i = 0; i < children.length; i ++ ) {
48419 const childNode = children[ i ];
48421 if ( childNode.name === nodeName || childNode.uuid === nodeName ) {
48427 const result = searchNodeSubtree( childNode.children );
48429 if ( result ) return result;
48437 const subTreeNode = searchNodeSubtree( root.children );
48439 if ( subTreeNode ) {
48441 return subTreeNode;
48451 // these are used to "
bind" a nonexistent property
48452 _getValue_unavailable() {}
48453 _setValue_unavailable() {}
48457 _getValue_direct( buffer, offset ) {
48459 buffer[ offset ] = this.targetObject[ this.propertyName ];
48463 _getValue_array( buffer, offset ) {
48465 const source = this.resolvedProperty;
48467 for ( let i = 0, n = source.length; i !== n; ++ i ) {
48469 buffer[ offset ++ ] = source[ i ];
48475 _getValue_arrayElement( buffer, offset ) {
48477 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ];
48481 _getValue_toArray( buffer, offset ) {
48483 this.resolvedProperty.toArray( buffer, offset );
48489 _setValue_direct( buffer, offset ) {
48491 this.targetObject[ this.propertyName ] = buffer[ offset ];
48495 _setValue_direct_setNeedsUpdate( buffer, offset ) {
48497 this.targetObject[ this.propertyName ] = buffer[ offset ];
48498 this.targetObject.needsUpdate = true;
48502 _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) {
48504 this.targetObject[ this.propertyName ] = buffer[ offset ];
48505 this.targetObject.matrixWorldNeedsUpdate = true;
48511 _setValue_array( buffer, offset ) {
48513 const dest = this.resolvedProperty;
48515 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48517 dest[ i ] = buffer[ offset ++ ];
48523 _setValue_array_setNeedsUpdate( buffer, offset ) {
48525 const dest = this.resolvedProperty;
48527 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48529 dest[ i ] = buffer[ offset ++ ];
48533 this.targetObject.needsUpdate = true;
48537 _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) {
48539 const dest = this.resolvedProperty;
48541 for ( let i = 0, n = dest.length; i !== n; ++ i ) {
48543 dest[ i ] = buffer[ offset ++ ];
48547 this.targetObject.matrixWorldNeedsUpdate = true;
48553 _setValue_arrayElement( buffer, offset ) {
48555 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48559 _setValue_arrayElement_setNeedsUpdate( buffer, offset ) {
48561 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48562 this.targetObject.needsUpdate = true;
48566 _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) {
48568 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ];
48569 this.targetObject.matrixWorldNeedsUpdate = true;
48575 _setValue_fromArray( buffer, offset ) {
48577 this.resolvedProperty.fromArray( buffer, offset );
48581 _setValue_fromArray_setNeedsUpdate( buffer, offset ) {
48583 this.resolvedProperty.fromArray( buffer, offset );
48584 this.targetObject.needsUpdate = true;
48588 _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) {
48590 this.resolvedProperty.fromArray( buffer, offset );
48591 this.targetObject.matrixWorldNeedsUpdate = true;
48595 _getValue_unbound( targetArray, offset ) {
48598 this.getValue( targetArray, offset );
48602 _setValue_unbound( sourceArray, offset ) {
48605 this.setValue( sourceArray, offset );
48609 // create getter / setter pair for a property in the scene graph
48612 let targetObject = this.node;
48613 const parsedPath = this.parsedPath;
48615 const objectName = parsedPath.objectName;
48616 const propertyName = parsedPath.propertyName;
48617 let propertyIndex = parsedPath.propertyIndex;
48619 if ( ! targetObject ) {
48621 targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName );
48623 this.node = targetObject;
48627 // set fail state so we can just 'return' on error
48628 this.getValue = this._getValue_unavailable;
48629 this.setValue = this._setValue_unavailable;
48631 // ensure there is a value node
48632 if ( ! targetObject ) {
48634 console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' );
48639 if ( objectName ) {
48641 let objectIndex = parsedPath.objectIndex;
48643 // special cases were we need to reach deeper into the hierarchy to get the face materials....
48644 switch ( objectName ) {
48648 if ( ! targetObject.material ) {
48650 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
48655 if ( ! targetObject.material.materials ) {
48657 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this );
48662 targetObject = targetObject.material.materials;
48668 if ( ! targetObject.skeleton ) {
48670 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this );
48675 // potential future optimization: skip this if propertyIndex is already an integer
48676 // and convert the integer string to a true integer.
48678 targetObject = targetObject.skeleton.bones;
48680 // support resolving morphTarget names into indices.
48681 for ( let i = 0; i < targetObject.length; i ++ ) {
48683 if ( targetObject[ i ].name === objectIndex ) {
48696 if ( 'map' in targetObject ) {
48698 targetObject = targetObject.map;
48703 if ( ! targetObject.material ) {
48705 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this );
48710 if ( ! targetObject.material.map ) {
48712 console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this );
48717 targetObject = targetObject.material.map;
48722 if ( targetObject[ objectName ] === undefined ) {
48724 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this );
48729 targetObject = targetObject[ objectName ];
48734 if ( objectIndex !== undefined ) {
48736 if ( targetObject[ objectIndex ] === undefined ) {
48738 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject );
48743 targetObject = targetObject[ objectIndex ];
48749 // resolve property
48750 const nodeProperty = targetObject[ propertyName ];
48752 if ( nodeProperty === undefined ) {
48754 const nodeName = parsedPath.nodeName;
48756 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName +
48757 '.' + propertyName + ' but it wasn\'t found.', targetObject );
48762 // determine versioning scheme
48763 let versioning = this.Versioning.None;
48765 this.targetObject = targetObject;
48767 if ( targetObject.needsUpdate !== undefined ) { // material
48769 versioning = this.Versioning.NeedsUpdate;
48771 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform
48773 versioning = this.Versioning.MatrixWorldNeedsUpdate;
48777 // determine how the property gets bound
48778 let bindingType = this.BindingType.Direct;
48780 if ( propertyIndex !== undefined ) {
48782 // access a sub element of the property array (only primitives are supported right now)
48784 if ( propertyName === 'morphTargetInfluences' ) {
48786 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer.
48788 // support resolving morphTarget names into indices.
48789 if ( ! targetObject.geometry ) {
48791 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this );
48796 if ( ! targetObject.geometry.morphAttributes ) {
48798 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this );
48803 if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) {
48805 propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ];
48811 bindingType = this.BindingType.ArrayElement;
48813 this.resolvedProperty = nodeProperty;
48814 this.propertyIndex = propertyIndex;
48816 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) {
48818 // must use copy for Object3D.Euler/Quaternion
48820 bindingType = this.BindingType.HasFromToArray;
48822 this.resolvedProperty = nodeProperty;
48824 } else if ( Array.isArray( nodeProperty ) ) {
48826 bindingType = this.BindingType.EntireArray;
48828 this.resolvedProperty = nodeProperty;
48832 this.propertyName = propertyName;
48836 // select getter / setter
48837 this.getValue = this.GetterByBindingType[ bindingType ];
48838 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ];
48846 // back to the prototype version of getValue / setValue
48847 // note: avoiding to mutate the shape of 'this' via 'delete'
48848 this.getValue = this._getValue_unbound;
48849 this.setValue = this._setValue_unbound;
48855 PropertyBinding.Composite = Composite;
48857 PropertyBinding.prototype.BindingType = {
48864 PropertyBinding.prototype.Versioning = {
48867 MatrixWorldNeedsUpdate: 2
48870 PropertyBinding.prototype.GetterByBindingType = [
48872 PropertyBinding.prototype._getValue_direct,
48873 PropertyBinding.prototype._getValue_array,
48874 PropertyBinding.prototype._getValue_arrayElement,
48875 PropertyBinding.prototype._getValue_toArray,
48879 PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [
48883 PropertyBinding.prototype._setValue_direct,
48884 PropertyBinding.prototype._setValue_direct_setNeedsUpdate,
48885 PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate,
48891 PropertyBinding.prototype._setValue_array,
48892 PropertyBinding.prototype._setValue_array_setNeedsUpdate,
48893 PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate,
48898 PropertyBinding.prototype._setValue_arrayElement,
48899 PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate,
48900 PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate,
48905 PropertyBinding.prototype._setValue_fromArray,
48906 PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate,
48907 PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate,
48942 class AnimationObjectGroup {
48946 this.isAnimationObjectGroup = true;
48948 this.uuid = generateUUID();
48950 // cached objects followed by the active ones
48951 this._objects = Array.prototype.slice.call( arguments );
48953 this.nCachedObjects_ = 0; // threshold
48954 // note: read by PropertyBinding.Composite
48956 const indices = {};
48957 this._indicesByUUID = indices; // for bookkeeping
48959 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
48961 indices[ arguments[ i ].uuid ] = i;
48965 this._paths = []; // inside: string
48966 this._parsedPaths = []; // inside: { we don't care, here }
48967 this._bindings = []; // inside: Array< PropertyBinding >
48968 this._bindingsIndicesByPath = {}; // inside: indices in these arrays
48970 const scope = this;
48977 return scope._objects.length;
48982 return this.total - scope.nCachedObjects_;
48986 get bindingsPerObject() {
48988 return scope._bindings.length;
48998 const objects = this._objects,
48999 indicesByUUID = this._indicesByUUID,
49000 paths = this._paths,
49001 parsedPaths = this._parsedPaths,
49002 bindings = this._bindings,
49003 nBindings = bindings.length;
49005 let knownObject = undefined,
49006 nObjects = objects.length,
49007 nCachedObjects = this.nCachedObjects_;
49009 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
49011 const object = arguments[ i ],
49012 uuid = object.uuid;
49013 let index = indicesByUUID[ uuid ];
49015 if ( index === undefined ) {
49017 // unknown object -> add it to the ACTIVE region
49019 index = nObjects ++;
49020 indicesByUUID[ uuid ] = index;
49021 objects.push( object );
49023 // accounting is done, now do the same for all bindings
49025 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49027 bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) );
49031 } else if ( index < nCachedObjects ) {
49033 knownObject = objects[ index ];
49035 // move existing object to the ACTIVE region
49037 const firstActiveIndex = -- nCachedObjects,
49038 lastCachedObject = objects[ firstActiveIndex ];
49040 indicesByUUID[ lastCachedObject.uuid ] = index;
49041 objects[ index ] = lastCachedObject;
49043 indicesByUUID[ uuid ] = firstActiveIndex;
49044 objects[ firstActiveIndex ] = object;
49046 // accounting is done, now do the same for all bindings
49048 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49050 const bindingsForPath = bindings[ j ],
49051 lastCached = bindingsForPath[ firstActiveIndex ];
49053 let binding = bindingsForPath[ index ];
49055 bindingsForPath[ index ] = lastCached;
49057 if ( binding === undefined ) {
49059 // since we do not bother to create new bindings
49060 // for objects that are cached, the binding may
49061 // or may not exist
49063 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] );
49067 bindingsForPath[ firstActiveIndex ] = binding;
49071 } else if ( objects[ index ] !== knownObject ) {
49073 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' +
49074 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' );
49076 } // else the object is already where we want it to be
49080 this.nCachedObjects_ = nCachedObjects;
49086 const objects = this._objects,
49087 indicesByUUID = this._indicesByUUID,
49088 bindings = this._bindings,
49089 nBindings = bindings.length;
49091 let nCachedObjects = this.nCachedObjects_;
49093 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
49095 const object = arguments[ i ],
49096 uuid = object.uuid,
49097 index = indicesByUUID[ uuid ];
49099 if ( index !== undefined && index >= nCachedObjects ) {
49101 // move existing object into the CACHED region
49103 const lastCachedIndex = nCachedObjects ++,
49104 firstActiveObject = objects[ lastCachedIndex ];
49106 indicesByUUID[ firstActiveObject.uuid ] = index;
49107 objects[ index ] = firstActiveObject;
49109 indicesByUUID[ uuid ] = lastCachedIndex;
49110 objects[ lastCachedIndex ] = object;
49112 // accounting is done, now do the same for all bindings
49114 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49116 const bindingsForPath = bindings[ j ],
49117 firstActive = bindingsForPath[ lastCachedIndex ],
49118 binding = bindingsForPath[ index ];
49120 bindingsForPath[ index ] = firstActive;
49121 bindingsForPath[ lastCachedIndex ] = binding;
49129 this.nCachedObjects_ = nCachedObjects;
49136 const objects = this._objects,
49137 indicesByUUID = this._indicesByUUID,
49138 bindings = this._bindings,
49139 nBindings = bindings.length;
49141 let nCachedObjects = this.nCachedObjects_,
49142 nObjects = objects.length;
49144 for ( let i = 0, n = arguments.length; i !== n; ++ i ) {
49146 const object = arguments[ i ],
49147 uuid = object.uuid,
49148 index = indicesByUUID[ uuid ];
49150 if ( index !== undefined ) {
49152 delete indicesByUUID[ uuid ];
49154 if ( index < nCachedObjects ) {
49156 // object is cached, shrink the CACHED region
49158 const firstActiveIndex = -- nCachedObjects,
49159 lastCachedObject = objects[ firstActiveIndex ],
49160 lastIndex = -- nObjects,
49161 lastObject = objects[ lastIndex ];
49163 // last cached object takes this object's place
49164 indicesByUUID[ lastCachedObject.uuid ] = index;
49165 objects[ index ] = lastCachedObject;
49167 // last object goes to the activated slot and pop
49168 indicesByUUID[ lastObject.uuid ] = firstActiveIndex;
49169 objects[ firstActiveIndex ] = lastObject;
49172 // accounting is done, now do the same for all bindings
49174 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49176 const bindingsForPath = bindings[ j ],
49177 lastCached = bindingsForPath[ firstActiveIndex ],
49178 last = bindingsForPath[ lastIndex ];
49180 bindingsForPath[ index ] = lastCached;
49181 bindingsForPath[ firstActiveIndex ] = last;
49182 bindingsForPath.pop();
49188 // object is active, just swap with the last and pop
49190 const lastIndex = -- nObjects,
49191 lastObject = objects[ lastIndex ];
49193 if ( lastIndex > 0 ) {
49195 indicesByUUID[ lastObject.uuid ] = index;
49199 objects[ index ] = lastObject;
49202 // accounting is done, now do the same for all bindings
49204 for ( let j = 0, m = nBindings; j !== m; ++ j ) {
49206 const bindingsForPath = bindings[ j ];
49208 bindingsForPath[ index ] = bindingsForPath[ lastIndex ];
49209 bindingsForPath.pop();
49213 } // cached or active
49215 } // if object is known
49219 this.nCachedObjects_ = nCachedObjects;
49223 // Internal interface used by befriended PropertyBinding.Composite:
49225 subscribe_( path, parsedPath ) {
49227 // returns an array of bindings for the given path that is changed
49228 // according to the contained objects in the group
49230 const indicesByPath = this._bindingsIndicesByPath;
49231 let index = indicesByPath[ path ];
49232 const bindings = this._bindings;
49234 if ( index !== undefined ) return bindings[ index ];
49236 const paths = this._paths,
49237 parsedPaths = this._parsedPaths,
49238 objects = this._objects,
49239 nObjects = objects.length,
49240 nCachedObjects = this.nCachedObjects_,
49241 bindingsForPath = new Array( nObjects );
49243 index = bindings.length;
49245 indicesByPath[ path ] = index;
49247 paths.push( path );
49248 parsedPaths.push( parsedPath );
49249 bindings.push( bindingsForPath );
49251 for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) {
49253 const object = objects[ i ];
49254 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath );
49258 return bindingsForPath;
49262 unsubscribe_( path ) {
49264 // tells the group to forget about a property path and no longer
49265 // update the array previously obtained with 'subscribe_'
49267 const indicesByPath = this._bindingsIndicesByPath,
49268 index = indicesByPath[ path ];
49270 if ( index !== undefined ) {
49272 const paths = this._paths,
49273 parsedPaths = this._parsedPaths,
49274 bindings = this._bindings,
49275 lastBindingsIndex = bindings.length - 1,
49276 lastBindings = bindings[ lastBindingsIndex ],
49277 lastBindingsPath = path[ lastBindingsIndex ];
49279 indicesByPath[ lastBindingsPath ] = index;
49281 bindings[ index ] = lastBindings;
49284 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ];
49287 paths[ index ] = paths[ lastBindingsIndex ];
49296 class AnimationAction {
49298 constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) {
49300 this._mixer = mixer;
49302 this._localRoot = localRoot;
49303 this.blendMode = blendMode;
49305 const tracks = clip.tracks,
49306 nTracks = tracks.length,
49307 interpolants = new Array( nTracks );
49309 const interpolantSettings = {
49310 endingStart: ZeroCurvatureEnding,
49311 endingEnd: ZeroCurvatureEnding
49314 for ( let i = 0; i !== nTracks; ++ i ) {
49316 const interpolant = tracks[ i ].createInterpolant( null );
49317 interpolants[ i ] = interpolant;
49318 interpolant.settings = interpolantSettings;
49322 this._interpolantSettings = interpolantSettings;
49324 this._interpolants = interpolants; // bound by the mixer
49326 // inside: PropertyMixer (managed by the mixer)
49327 this._propertyBindings = new Array( nTracks );
49329 this._cacheIndex = null; // for the memory manager
49330 this._byClipCacheIndex = null; // for the memory manager
49332 this._timeScaleInterpolant = null;
49333 this._weightInterpolant = null;
49335 this.loop = LoopRepeat;
49336 this._loopCount = - 1;
49338 // global mixer time when the action is to be started
49339 // it's set back to 'null' upon start of the action
49340 this._startTime = null;
49342 // scaled local time of the action
49343 // gets clamped or wrapped to 0..clip.duration according to loop
49346 this.timeScale = 1;
49347 this._effectiveTimeScale = 1;
49350 this._effectiveWeight = 1;
49352 this.repetitions = Infinity; // no. of repetitions when looping
49354 this.paused = false; // true -> zero effective time scale
49355 this.enabled = true; // false -> zero effective weight
49357 this.clampWhenFinished = false;// keep feeding the last frame?
49359 this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate
49360 this.zeroSlopeAtEnd = true;// clips for start, loop and end
49364 // State & Scheduling
49368 this._mixer._activateAction( this );
49376 this._mixer._deactivateAction( this );
49378 return this.reset();
49384 this.paused = false;
49385 this.enabled = true;
49387 this.time = 0; // restart clip
49388 this._loopCount = - 1;// forget previous loops
49389 this._startTime = null;// forget scheduling
49391 return this.stopFading().stopWarping();
49397 return this.enabled && ! this.paused && this.timeScale !== 0 &&
49398 this._startTime === null && this._mixer._isActiveAction( this );
49402 // return true when play has been called
49405 return this._mixer._isActiveAction( this );
49411 this._startTime = time;
49417 setLoop( mode, repetitions ) {
49420 this.repetitions = repetitions;
49428 // set the weight stopping any scheduled fading
49429 // although .enabled = false yields an effective weight of zero, this
49430 // method does *not* change .enabled, because it would be confusing
49431 setEffectiveWeight( weight ) {
49433 this.weight = weight;
49435 // note: same logic as when updated at runtime
49436 this._effectiveWeight = this.enabled ? weight : 0;
49438 return this.stopFading();
49442 // return the weight considering fading and .enabled
49443 getEffectiveWeight() {
49445 return this._effectiveWeight;
49449 fadeIn( duration ) {
49451 return this._scheduleFading( duration, 0, 1 );
49455 fadeOut( duration ) {
49457 return this._scheduleFading( duration, 1, 0 );
49461 crossFadeFrom( fadeOutAction, duration, warp ) {
49463 fadeOutAction.fadeOut( duration );
49464 this.fadeIn( duration );
49468 const fadeInDuration = this._clip.duration,
49469 fadeOutDuration = fadeOutAction._clip.duration,
49471 startEndRatio = fadeOutDuration / fadeInDuration,
49472 endStartRatio = fadeInDuration / fadeOutDuration;
49474 fadeOutAction.warp( 1.0, startEndRatio, duration );
49475 this.warp( endStartRatio, 1.0, duration );
49483 crossFadeTo( fadeInAction, duration, warp ) {
49485 return fadeInAction.crossFadeFrom( this, duration, warp );
49491 const weightInterpolant = this._weightInterpolant;
49493 if ( weightInterpolant !== null ) {
49495 this._weightInterpolant = null;
49496 this._mixer._takeBackControlInterpolant( weightInterpolant );
49504 // Time Scale Control
49506 // set the time scale stopping any scheduled warping
49507 // although .paused = true yields an effective time scale of zero, this
49508 // method does *not* change .paused, because it would be confusing
49509 setEffectiveTimeScale( timeScale ) {
49511 this.timeScale = timeScale;
49512 this._effectiveTimeScale = this.paused ? 0 : timeScale;
49514 return this.stopWarping();
49518 // return the time scale considering warping and .paused
49519 getEffectiveTimeScale() {
49521 return this._effectiveTimeScale;
49525 setDuration( duration ) {
49527 this.timeScale = this._clip.duration / duration;
49529 return this.stopWarping();
49533 syncWith( action ) {
49535 this.time = action.time;
49536 this.timeScale = action.timeScale;
49538 return this.stopWarping();
49544 return this.warp( this._effectiveTimeScale, 0, duration );
49548 warp( startTimeScale, endTimeScale, duration ) {
49550 const mixer = this._mixer,
49552 timeScale = this.timeScale;
49554 let interpolant = this._timeScaleInterpolant;
49556 if ( interpolant === null ) {
49558 interpolant = mixer._lendControlInterpolant();
49559 this._timeScaleInterpolant = interpolant;
49563 const times = interpolant.parameterPositions,
49564 values = interpolant.sampleValues;
49567 times[ 1 ] = now + duration;
49569 values[ 0 ] = startTimeScale / timeScale;
49570 values[ 1 ] = endTimeScale / timeScale;
49578 const timeScaleInterpolant = this._timeScaleInterpolant;
49580 if ( timeScaleInterpolant !== null ) {
49582 this._timeScaleInterpolant = null;
49583 this._mixer._takeBackControlInterpolant( timeScaleInterpolant );
49591 // Object Accessors
49595 return this._mixer;
49607 return this._localRoot || this._mixer._root;
49613 _update( time, deltaTime, timeDirection, accuIndex ) {
49615 // called by the mixer
49617 if ( ! this.enabled ) {
49619 // call ._updateWeight() to update ._effectiveWeight
49621 this._updateWeight( time );
49626 const startTime = this._startTime;
49628 if ( startTime !== null ) {
49630 // check for scheduled start of action
49632 const timeRunning = ( time - startTime ) * timeDirection;
49633 if ( timeRunning < 0 || timeDirection === 0 ) {
49640 this._startTime = null; // unschedule
49641 deltaTime = timeDirection * timeRunning;
49647 // apply time scale and advance time
49649 deltaTime *= this._updateTimeScale( time );
49650 const clipTime = this._updateTime( deltaTime );
49652 // note: _updateTime may disable the action resulting in
49653 // an effective weight of 0
49655 const weight = this._updateWeight( time );
49657 if ( weight > 0 ) {
49659 const interpolants = this._interpolants;
49660 const propertyMixers = this._propertyBindings;
49662 switch ( this.blendMode ) {
49664 case AdditiveAnimationBlendMode:
49666 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
49668 interpolants[ j ].evaluate( clipTime );
49669 propertyMixers[ j ].accumulateAdditive( weight );
49675 case NormalAnimationBlendMode:
49678 for ( let j = 0, m = interpolants.length; j !== m; ++ j ) {
49680 interpolants[ j ].evaluate( clipTime );
49681 propertyMixers[ j ].accumulate( accuIndex, weight );
49691 _updateWeight( time ) {
49695 if ( this.enabled ) {
49697 weight = this.weight;
49698 const interpolant = this._weightInterpolant;
49700 if ( interpolant !== null ) {
49702 const interpolantValue = interpolant.evaluate( time )[ 0 ];
49704 weight *= interpolantValue;
49706 if ( time > interpolant.parameterPositions[ 1 ] ) {
49710 if ( interpolantValue === 0 ) {
49712 // faded out, disable
49713 this.enabled = false;
49723 this._effectiveWeight = weight;
49728 _updateTimeScale( time ) {
49732 if ( ! this.paused ) {
49734 timeScale = this.timeScale;
49736 const interpolant = this._timeScaleInterpolant;
49738 if ( interpolant !== null ) {
49740 const interpolantValue = interpolant.evaluate( time )[ 0 ];
49742 timeScale *= interpolantValue;
49744 if ( time > interpolant.parameterPositions[ 1 ] ) {
49746 this.stopWarping();
49748 if ( timeScale === 0 ) {
49750 // motion has halted, pause
49751 this.paused = true;
49755 // warp done - apply final time scale
49756 this.timeScale = timeScale;
49766 this._effectiveTimeScale = timeScale;
49771 _updateTime( deltaTime ) {
49773 const duration = this._clip.duration;
49774 const loop = this.loop;
49776 let time = this.time + deltaTime;
49777 let loopCount = this._loopCount;
49779 const pingPong = ( loop === LoopPingPong );
49781 if ( deltaTime === 0 ) {
49783 if ( loopCount === - 1 ) return time;
49785 return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time;
49789 if ( loop === LoopOnce ) {
49791 if ( loopCount === - 1 ) {
49795 this._loopCount = 0;
49796 this._setEndings( true, true, false );
49802 if ( time >= duration ) {
49806 } else if ( time < 0 ) {
49818 if ( this.clampWhenFinished ) this.paused = true;
49819 else this.enabled = false;
49823 this._mixer.dispatchEvent( {
49824 type: 'finished', action: this,
49825 direction: deltaTime < 0 ? - 1 : 1
49830 } else { // repetitive Repeat or PingPong
49832 if ( loopCount === - 1 ) {
49836 if ( deltaTime >= 0 ) {
49840 this._setEndings( true, this.repetitions === 0, pingPong );
49844 // when looping in reverse direction, the initial
49845 // transition through zero counts as a repetition,
49846 // so leave loopCount at -1
49848 this._setEndings( this.repetitions === 0, true, pingPong );
49854 if ( time >= duration || time < 0 ) {
49858 const loopDelta = Math.floor( time / duration ); // signed
49859 time -= duration * loopDelta;
49861 loopCount += Math.abs( loopDelta );
49863 const pending = this.repetitions - loopCount;
49865 if ( pending <= 0 ) {
49867 // have to stop (switch state, clamp time, fire event)
49869 if ( this.clampWhenFinished ) this.paused = true;
49870 else this.enabled = false;
49872 time = deltaTime > 0 ? duration : 0;
49876 this._mixer.dispatchEvent( {
49877 type: 'finished', action: this,
49878 direction: deltaTime > 0 ? 1 : - 1
49885 if ( pending === 1 ) {
49887 // entering the last round
49889 const atStart = deltaTime < 0;
49890 this._setEndings( atStart, ! atStart, pingPong );
49894 this._setEndings( false, false, pingPong );
49898 this._loopCount = loopCount;
49902 this._mixer.dispatchEvent( {
49903 type: 'loop', action: this, loopDelta: loopDelta
49914 if ( pingPong && ( loopCount & 1 ) === 1 ) {
49916 // invert time for the "pong
round"
49918 return duration - time;
49928 _setEndings( atStart, atEnd, pingPong ) {
49930 const settings = this._interpolantSettings;
49934 settings.endingStart = ZeroSlopeEnding;
49935 settings.endingEnd = ZeroSlopeEnding;
49939 // assuming for LoopOnce atStart == atEnd == true
49943 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding;
49947 settings.endingStart = WrapAroundEnding;
49953 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding;
49957 settings.endingEnd = WrapAroundEnding;
49965 _scheduleFading( duration, weightNow, weightThen ) {
49967 const mixer = this._mixer, now = mixer.time;
49968 let interpolant = this._weightInterpolant;
49970 if ( interpolant === null ) {
49972 interpolant = mixer._lendControlInterpolant();
49973 this._weightInterpolant = interpolant;
49977 const times = interpolant.parameterPositions,
49978 values = interpolant.sampleValues;
49981 values[ 0 ] = weightNow;
49982 times[ 1 ] = now + duration;
49983 values[ 1 ] = weightThen;
49991 const _controlInterpolantsResultBuffer = new Float32Array( 1 );
49994 class AnimationMixer extends EventDispatcher {
49996 constructor( root ) {
50001 this._initMemoryManager();
50002 this._accuIndex = 0;
50004 this.timeScale = 1.0;
50008 _bindAction( action, prototypeAction ) {
50010 const root = action._localRoot || this._root,
50011 tracks = action._clip.tracks,
50012 nTracks = tracks.length,
50013 bindings = action._propertyBindings,
50014 interpolants = action._interpolants,
50015 rootUuid = root.uuid,
50016 bindingsByRoot = this._bindingsByRootAndName;
50018 let bindingsByName = bindingsByRoot[ rootUuid ];
50020 if ( bindingsByName === undefined ) {
50022 bindingsByName = {};
50023 bindingsByRoot[ rootUuid ] = bindingsByName;
50027 for ( let i = 0; i !== nTracks; ++ i ) {
50029 const track = tracks[ i ],
50030 trackName = track.name;
50032 let binding = bindingsByName[ trackName ];
50034 if ( binding !== undefined ) {
50036 ++ binding.referenceCount;
50037 bindings[ i ] = binding;
50041 binding = bindings[ i ];
50043 if ( binding !== undefined ) {
50045 // existing binding, make sure the cache knows
50047 if ( binding._cacheIndex === null ) {
50049 ++ binding.referenceCount;
50050 this._addInactiveBinding( binding, rootUuid, trackName );
50058 const path = prototypeAction && prototypeAction.
50059 _propertyBindings[ i ].binding.parsedPath;
50061 binding = new PropertyMixer(
50062 PropertyBinding.create( root, trackName, path ),
50063 track.ValueTypeName, track.getValueSize() );
50065 ++ binding.referenceCount;
50066 this._addInactiveBinding( binding, rootUuid, trackName );
50068 bindings[ i ] = binding;
50072 interpolants[ i ].resultBuffer = binding.buffer;
50078 _activateAction( action ) {
50080 if ( ! this._isActiveAction( action ) ) {
50082 if ( action._cacheIndex === null ) {
50084 // this action has been forgotten by the cache, but the user
50085 // appears to be still using it -> rebind
50087 const rootUuid = ( action._localRoot || this._root ).uuid,
50088 clipUuid = action._clip.uuid,
50089 actionsForClip = this._actionsByClip[ clipUuid ];
50091 this._bindAction( action,
50092 actionsForClip && actionsForClip.knownActions[ 0 ] );
50094 this._addInactiveAction( action, clipUuid, rootUuid );
50098 const bindings = action._propertyBindings;
50100 // increment reference counts / sort out state
50101 for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
50103 const binding = bindings[ i ];
50105 if ( binding.useCount ++ === 0 ) {
50107 this._lendBinding( binding );
50108 binding.saveOriginalState();
50114 this._lendAction( action );
50120 _deactivateAction( action ) {
50122 if ( this._isActiveAction( action ) ) {
50124 const bindings = action._propertyBindings;
50126 // decrement reference counts / sort out state
50127 for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
50129 const binding = bindings[ i ];
50131 if ( -- binding.useCount === 0 ) {
50133 binding.restoreOriginalState();
50134 this._takeBackBinding( binding );
50140 this._takeBackAction( action );
50148 _initMemoryManager() {
50150 this._actions = []; // 'nActiveActions' followed by inactive ones
50151 this._nActiveActions = 0;
50153 this._actionsByClip = {};
50156 // knownActions: Array< AnimationAction > - used as prototypes
50157 // actionByRoot: AnimationAction - lookup
50161 this._bindings = []; // 'nActiveBindings' followed by inactive ones
50162 this._nActiveBindings = 0;
50164 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer >
50167 this._controlInterpolants = []; // same game as above
50168 this._nActiveControlInterpolants = 0;
50170 const scope = this;
50177 return scope._actions.length;
50182 return scope._nActiveActions;
50189 return scope._bindings.length;
50194 return scope._nActiveBindings;
50198 controlInterpolants: {
50201 return scope._controlInterpolants.length;
50206 return scope._nActiveControlInterpolants;
50215 // Memory management for AnimationAction objects
50217 _isActiveAction( action ) {
50219 const index = action._cacheIndex;
50220 return index !== null && index < this._nActiveActions;
50224 _addInactiveAction( action, clipUuid, rootUuid ) {
50226 const actions = this._actions,
50227 actionsByClip = this._actionsByClip;
50229 let actionsForClip = actionsByClip[ clipUuid ];
50231 if ( actionsForClip === undefined ) {
50235 knownActions: [ action ],
50240 action._byClipCacheIndex = 0;
50242 actionsByClip[ clipUuid ] = actionsForClip;
50246 const knownActions = actionsForClip.knownActions;
50248 action._byClipCacheIndex = knownActions.length;
50249 knownActions.push( action );
50253 action._cacheIndex = actions.length;
50254 actions.push( action );
50256 actionsForClip.actionByRoot[ rootUuid ] = action;
50260 _removeInactiveAction( action ) {
50262 const actions = this._actions,
50263 lastInactiveAction = actions[ actions.length - 1 ],
50264 cacheIndex = action._cacheIndex;
50266 lastInactiveAction._cacheIndex = cacheIndex;
50267 actions[ cacheIndex ] = lastInactiveAction;
50270 action._cacheIndex = null;
50273 const clipUuid = action._clip.uuid,
50274 actionsByClip = this._actionsByClip,
50275 actionsForClip = actionsByClip[ clipUuid ],
50276 knownActionsForClip = actionsForClip.knownActions,
50279 knownActionsForClip[ knownActionsForClip.length - 1 ],
50281 byClipCacheIndex = action._byClipCacheIndex;
50283 lastKnownAction._byClipCacheIndex = byClipCacheIndex;
50284 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction;
50285 knownActionsForClip.pop();
50287 action._byClipCacheIndex = null;
50290 const actionByRoot = actionsForClip.actionByRoot,
50291 rootUuid = ( action._localRoot || this._root ).uuid;
50293 delete actionByRoot[ rootUuid ];
50295 if ( knownActionsForClip.length === 0 ) {
50297 delete actionsByClip[ clipUuid ];
50301 this._removeInactiveBindingsForAction( action );
50305 _removeInactiveBindingsForAction( action ) {
50307 const bindings = action._propertyBindings;
50309 for ( let i = 0, n = bindings.length; i !== n; ++ i ) {
50311 const binding = bindings[ i ];
50313 if ( -- binding.referenceCount === 0 ) {
50315 this._removeInactiveBinding( binding );
50323 _lendAction( action ) {
50325 // [ active actions | inactive actions ]
50326 // [ active actions >| inactive actions ]
50331 const actions = this._actions,
50332 prevIndex = action._cacheIndex,
50334 lastActiveIndex = this._nActiveActions ++,
50336 firstInactiveAction = actions[ lastActiveIndex ];
50338 action._cacheIndex = lastActiveIndex;
50339 actions[ lastActiveIndex ] = action;
50341 firstInactiveAction._cacheIndex = prevIndex;
50342 actions[ prevIndex ] = firstInactiveAction;
50346 _takeBackAction( action ) {
50348 // [ active actions | inactive actions ]
50349 // [ active actions |< inactive actions ]
50354 const actions = this._actions,
50355 prevIndex = action._cacheIndex,
50357 firstInactiveIndex = -- this._nActiveActions,
50359 lastActiveAction = actions[ firstInactiveIndex ];
50361 action._cacheIndex = firstInactiveIndex;
50362 actions[ firstInactiveIndex ] = action;
50364 lastActiveAction._cacheIndex = prevIndex;
50365 actions[ prevIndex ] = lastActiveAction;
50369 // Memory management for PropertyMixer objects
50371 _addInactiveBinding( binding, rootUuid, trackName ) {
50373 const bindingsByRoot = this._bindingsByRootAndName,
50374 bindings = this._bindings;
50376 let bindingByName = bindingsByRoot[ rootUuid ];
50378 if ( bindingByName === undefined ) {
50380 bindingByName = {};
50381 bindingsByRoot[ rootUuid ] = bindingByName;
50385 bindingByName[ trackName ] = binding;
50387 binding._cacheIndex = bindings.length;
50388 bindings.push( binding );
50392 _removeInactiveBinding( binding ) {
50394 const bindings = this._bindings,
50395 propBinding = binding.binding,
50396 rootUuid = propBinding.rootNode.uuid,
50397 trackName = propBinding.path,
50398 bindingsByRoot = this._bindingsByRootAndName,
50399 bindingByName = bindingsByRoot[ rootUuid ],
50401 lastInactiveBinding = bindings[ bindings.length - 1 ],
50402 cacheIndex = binding._cacheIndex;
50404 lastInactiveBinding._cacheIndex = cacheIndex;
50405 bindings[ cacheIndex ] = lastInactiveBinding;
50408 delete bindingByName[ trackName ];
50410 if ( Object.keys( bindingByName ).length === 0 ) {
50412 delete bindingsByRoot[ rootUuid ];
50418 _lendBinding( binding ) {
50420 const bindings = this._bindings,
50421 prevIndex = binding._cacheIndex,
50423 lastActiveIndex = this._nActiveBindings ++,
50425 firstInactiveBinding = bindings[ lastActiveIndex ];
50427 binding._cacheIndex = lastActiveIndex;
50428 bindings[ lastActiveIndex ] = binding;
50430 firstInactiveBinding._cacheIndex = prevIndex;
50431 bindings[ prevIndex ] = firstInactiveBinding;
50435 _takeBackBinding( binding ) {
50437 const bindings = this._bindings,
50438 prevIndex = binding._cacheIndex,
50440 firstInactiveIndex = -- this._nActiveBindings,
50442 lastActiveBinding = bindings[ firstInactiveIndex ];
50444 binding._cacheIndex = firstInactiveIndex;
50445 bindings[ firstInactiveIndex ] = binding;
50447 lastActiveBinding._cacheIndex = prevIndex;
50448 bindings[ prevIndex ] = lastActiveBinding;
50453 // Memory management of Interpolants for weight and time scale
50455 _lendControlInterpolant() {
50457 const interpolants = this._controlInterpolants,
50458 lastActiveIndex = this._nActiveControlInterpolants ++;
50460 let interpolant = interpolants[ lastActiveIndex ];
50462 if ( interpolant === undefined ) {
50464 interpolant = new LinearInterpolant(
50465 new Float32Array( 2 ), new Float32Array( 2 ),
50466 1, _controlInterpolantsResultBuffer );
50468 interpolant.__cacheIndex = lastActiveIndex;
50469 interpolants[ lastActiveIndex ] = interpolant;
50473 return interpolant;
50477 _takeBackControlInterpolant( interpolant ) {
50479 const interpolants = this._controlInterpolants,
50480 prevIndex = interpolant.__cacheIndex,
50482 firstInactiveIndex = -- this._nActiveControlInterpolants,
50484 lastActiveInterpolant = interpolants[ firstInactiveIndex ];
50486 interpolant.__cacheIndex = firstInactiveIndex;
50487 interpolants[ firstInactiveIndex ] = interpolant;
50489 lastActiveInterpolant.__cacheIndex = prevIndex;
50490 interpolants[ prevIndex ] = lastActiveInterpolant;
50494 // return an action for a clip optionally using a custom root target
50495 // object (this method allocates a lot of dynamic memory in case a
50496 // previously unknown clip/root combination is specified)
50497 clipAction( clip, optionalRoot, blendMode ) {
50499 const root = optionalRoot || this._root,
50500 rootUuid = root.uuid;
50502 let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip;
50504 const clipUuid = clipObject !== null ? clipObject.uuid : clip;
50506 const actionsForClip = this._actionsByClip[ clipUuid ];
50507 let prototypeAction = null;
50509 if ( blendMode === undefined ) {
50511 if ( clipObject !== null ) {
50513 blendMode = clipObject.blendMode;
50517 blendMode = NormalAnimationBlendMode;
50523 if ( actionsForClip !== undefined ) {
50525 const existingAction = actionsForClip.actionByRoot[ rootUuid ];
50527 if ( existingAction !== undefined && existingAction.blendMode === blendMode ) {
50529 return existingAction;
50533 // we know the clip, so we don't have to parse all
50534 // the bindings again but can just copy
50535 prototypeAction = actionsForClip.knownActions[ 0 ];
50537 // also, take the clip from the prototype action
50538 if ( clipObject === null )
50539 clipObject = prototypeAction._clip;
50543 // clip must be known when specified via string
50544 if ( clipObject === null ) return null;
50546 // allocate all resources required to run it
50547 const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode );
50549 this._bindAction( newAction, prototypeAction );
50551 // and make the action known to the memory manager
50552 this._addInactiveAction( newAction, clipUuid, rootUuid );
50558 // get an existing action
50559 existingAction( clip, optionalRoot ) {
50561 const root = optionalRoot || this._root,
50562 rootUuid = root.uuid,
50564 clipObject = typeof clip === 'string' ?
50565 AnimationClip.findByName( root, clip ) : clip,
50567 clipUuid = clipObject ? clipObject.uuid : clip,
50569 actionsForClip = this._actionsByClip[ clipUuid ];
50571 if ( actionsForClip !== undefined ) {
50573 return actionsForClip.actionByRoot[ rootUuid ] || null;
50581 // deactivates all previously scheduled actions
50584 const actions = this._actions,
50585 nActions = this._nActiveActions;
50587 for ( let i = nActions - 1; i >= 0; -- i ) {
50589 actions[ i ].stop();
50597 // advance the time and update apply the animation
50598 update( deltaTime ) {
50600 deltaTime *= this.timeScale;
50602 const actions = this._actions,
50603 nActions = this._nActiveActions,
50605 time = this.time += deltaTime,
50606 timeDirection = Math.sign( deltaTime ),
50608 accuIndex = this._accuIndex ^= 1;
50610 // run active actions
50612 for ( let i = 0; i !== nActions; ++ i ) {
50614 const action = actions[ i ];
50616 action._update( time, deltaTime, timeDirection, accuIndex );
50620 // update scene graph
50622 const bindings = this._bindings,
50623 nBindings = this._nActiveBindings;
50625 for ( let i = 0; i !== nBindings; ++ i ) {
50627 bindings[ i ].apply( accuIndex );
50635 // Allows you to seek to a specific time in an animation.
50636 setTime( timeInSeconds ) {
50638 this.time = 0; // Zero out time attribute for AnimationMixer object;
50639 for ( let i = 0; i < this._actions.length; i ++ ) {
50641 this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects.
50645 return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object.
50649 // return this mixer's root target object
50656 // free all resources specific to a particular clip
50657 uncacheClip( clip ) {
50659 const actions = this._actions,
50660 clipUuid = clip.uuid,
50661 actionsByClip = this._actionsByClip,
50662 actionsForClip = actionsByClip[ clipUuid ];
50664 if ( actionsForClip !== undefined ) {
50666 // note: just calling _removeInactiveAction would mess up the
50667 // iteration state and also require updating the state we can
50670 const actionsToRemove = actionsForClip.knownActions;
50672 for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) {
50674 const action = actionsToRemove[ i ];
50676 this._deactivateAction( action );
50678 const cacheIndex = action._cacheIndex,
50679 lastInactiveAction = actions[ actions.length - 1 ];
50681 action._cacheIndex = null;
50682 action._byClipCacheIndex = null;
50684 lastInactiveAction._cacheIndex = cacheIndex;
50685 actions[ cacheIndex ] = lastInactiveAction;
50688 this._removeInactiveBindingsForAction( action );
50692 delete actionsByClip[ clipUuid ];
50698 // free all resources specific to a particular root target object
50699 uncacheRoot( root ) {
50701 const rootUuid = root.uuid,
50702 actionsByClip = this._actionsByClip;
50704 for ( const clipUuid in actionsByClip ) {
50706 const actionByRoot = actionsByClip[ clipUuid ].actionByRoot,
50707 action = actionByRoot[ rootUuid ];
50709 if ( action !== undefined ) {
50711 this._deactivateAction( action );
50712 this._removeInactiveAction( action );
50718 const bindingsByRoot = this._bindingsByRootAndName,
50719 bindingByName = bindingsByRoot[ rootUuid ];
50721 if ( bindingByName !== undefined ) {
50723 for ( const trackName in bindingByName ) {
50725 const binding = bindingByName[ trackName ];
50726 binding.restoreOriginalState();
50727 this._removeInactiveBinding( binding );
50735 // remove a targeted clip from the cache
50736 uncacheAction( clip, optionalRoot ) {
50738 const action = this.existingAction( clip, optionalRoot );
50740 if ( action !== null ) {
50742 this._deactivateAction( action );
50743 this._removeInactiveAction( action );
50753 constructor( value ) {
50755 this.value = value;
50761 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() );
50769 class UniformsGroup extends EventDispatcher {
50775 this.isUniformsGroup = true;
50777 Object.defineProperty( this, 'id', { value: _id ++ } );
50781 this.usage = StaticDrawUsage;
50782 this.uniforms = [];
50788 this.uniforms.push( uniform );
50794 remove( uniform ) {
50796 const index = this.uniforms.indexOf( uniform );
50798 if ( index !== - 1 ) this.uniforms.splice( index, 1 );
50812 setUsage( value ) {
50814 this.usage = value;
50822 this.dispatchEvent( { type: 'dispose' } );
50830 this.name = source.name;
50831 this.usage = source.usage;
50833 const uniformsSource = source.uniforms;
50835 this.uniforms.length = 0;
50837 for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) {
50839 const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ];
50841 for ( let j = 0; j < uniforms.length; j ++ ) {
50843 this.uniforms.push( uniforms[ j ].clone() );
50855 return new this.constructor().copy( this );
50861 class InstancedInterleavedBuffer extends InterleavedBuffer {
50863 constructor( array, stride, meshPerAttribute = 1 ) {
50865 super( array, stride );
50867 this.isInstancedInterleavedBuffer = true;
50869 this.meshPerAttribute = meshPerAttribute;
50875 super.copy( source );
50877 this.meshPerAttribute = source.meshPerAttribute;
50885 const ib = super.clone( data );
50887 ib.meshPerAttribute = this.meshPerAttribute;
50895 const json = super.toJSON( data );
50897 json.isInstancedInterleavedBuffer = true;
50898 json.meshPerAttribute = this.meshPerAttribute;
50906 class GLBufferAttribute {
50908 constructor( buffer, type, itemSize, elementSize, count ) {
50910 this.isGLBufferAttribute = true;
50914 this.buffer = buffer;
50916 this.itemSize = itemSize;
50917 this.elementSize = elementSize;
50918 this.count = count;
50924 set needsUpdate( value ) {
50926 if ( value === true ) this.version ++;
50930 setBuffer( buffer ) {
50932 this.buffer = buffer;
50938 setType( type, elementSize ) {
50941 this.elementSize = elementSize;
50947 setItemSize( itemSize ) {
50949 this.itemSize = itemSize;
50955 setCount( count ) {
50957 this.count = count;
50967 constructor( origin, direction, near = 0, far = Infinity ) {
50969 this.ray = new Ray( origin, direction );
50970 // direction is assumed to be normalized (for accurate distance calculations)
50974 this.camera = null;
50975 this.layers = new Layers();
50979 Line: { threshold: 1 },
50981 Points: { threshold: 1 },
50987 set( origin, direction ) {
50989 // direction is assumed to be normalized (for accurate distance calculations)
50991 this.ray.set( origin, direction );
50995 setFromCamera( coords, camera ) {
50997 if ( camera.isPerspectiveCamera ) {
50999 this.ray.origin.setFromMatrixPosition( camera.matrixWorld );
51000 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize();
51001 this.camera = camera;
51003 } else if ( camera.isOrthographicCamera ) {
51005 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera
51006 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld );
51007 this.camera = camera;
51011 console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type );
51017 intersectObject( object, recursive = true, intersects = [] ) {
51019 intersectObject( object, this, intersects, recursive );
51021 intersects.sort( ascSort );
51027 intersectObjects( objects, recursive = true, intersects = [] ) {
51029 for ( let i = 0, l = objects.length; i < l; i ++ ) {
51031 intersectObject( objects[ i ], this, intersects, recursive );
51035 intersects.sort( ascSort );
51043 function ascSort( a, b ) {
51045 return a.distance - b.distance;
51049 function intersectObject( object, raycaster, intersects, recursive ) {
51051 if ( object.layers.test( raycaster.layers ) ) {
51053 object.raycast( raycaster, intersects );
51057 if ( recursive === true ) {
51059 const children = object.children;
51061 for ( let i = 0, l = children.length; i < l; i ++ ) {
51063 intersectObject( children[ i ], raycaster, intersects, true );
51081 constructor( radius = 1, phi = 0, theta = 0 ) {
51083 this.radius = radius;
51084 this.phi = phi; // polar angle
51085 this.theta = theta; // azimuthal angle
51091 set( radius, phi, theta ) {
51093 this.radius = radius;
51095 this.theta = theta;
51103 this.radius = other.radius;
51104 this.phi = other.phi;
51105 this.theta = other.theta;
51111 // restrict phi to be between EPS and PI-EPS
51114 const EPS = 0.000001;
51115 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) );
51121 setFromVector3( v ) {
51123 return this.setFromCartesianCoords( v.x, v.y, v.z );
51127 setFromCartesianCoords( x, y, z ) {
51129 this.radius = Math.sqrt( x * x + y * y + z * z );
51131 if ( this.radius === 0 ) {
51138 this.theta = Math.atan2( x, z );
51139 this.phi = Math.acos( clamp( y / this.radius, - 1, 1 ) );
51149 return new this.constructor().copy( this );
51159 class Cylindrical {
51161 constructor( radius = 1, theta = 0, y = 0 ) {
51163 this.radius = radius; // distance from the origin to a point in the x-z plane
51164 this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis
51165 this.y = y; // height above the x-z plane
51171 set( radius, theta, y ) {
51173 this.radius = radius;
51174 this.theta = theta;
51183 this.radius = other.radius;
51184 this.theta = other.theta;
51191 setFromVector3( v ) {
51193 return this.setFromCartesianCoords( v.x, v.y, v.z );
51197 setFromCartesianCoords( x, y, z ) {
51199 this.radius = Math.sqrt( x * x + z * z );
51200 this.theta = Math.atan2( x, z );
51209 return new this.constructor().copy( this );
51215 const _vector$4 = /*@__PURE__*/ new Vector2();
51219 constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) {
51221 this.isBox2 = true;
51230 this.min.copy( min );
51231 this.max.copy( max );
51237 setFromPoints( points ) {
51241 for ( let i = 0, il = points.length; i < il; i ++ ) {
51243 this.expandByPoint( points[ i ] );
51251 setFromCenterAndSize( center, size ) {
51253 const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 );
51254 this.min.copy( center ).sub( halfSize );
51255 this.max.copy( center ).add( halfSize );
51263 return new this.constructor().copy( this );
51269 this.min.copy( box.min );
51270 this.max.copy( box.max );
51278 this.min.x = this.min.y = + Infinity;
51279 this.max.x = this.max.y = - Infinity;
51287 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes
51289 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y );
51293 getCenter( target ) {
51295 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 );
51299 getSize( target ) {
51301 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min );
51305 expandByPoint( point ) {
51307 this.min.min( point );
51308 this.max.max( point );
51314 expandByVector( vector ) {
51316 this.min.sub( vector );
51317 this.max.add( vector );
51323 expandByScalar( scalar ) {
51325 this.min.addScalar( - scalar );
51326 this.max.addScalar( scalar );
51332 containsPoint( point ) {
51334 return point.x < this.min.x || point.x > this.max.x ||
51335 point.y < this.min.y || point.y > this.max.y ? false : true;
51339 containsBox( box ) {
51341 return this.min.x <= box.min.x && box.max.x <= this.max.x &&
51342 this.min.y <= box.min.y && box.max.y <= this.max.y;
51346 getParameter( point, target ) {
51348 // This can potentially have a divide by zero if the box
51349 // has a size dimension of 0.
51352 ( point.x - this.min.x ) / ( this.max.x - this.min.x ),
51353 ( point.y - this.min.y ) / ( this.max.y - this.min.y )
51358 intersectsBox( box ) {
51360 // using 4 splitting planes to rule out intersections
51362 return box.max.x < this.min.x || box.min.x > this.max.x ||
51363 box.max.y < this.min.y || box.min.y > this.max.y ? false : true;
51367 clampPoint( point, target ) {
51369 return target.copy( point ).clamp( this.min, this.max );
51373 distanceToPoint( point ) {
51375 return this.clampPoint( point, _vector$4 ).distanceTo( point );
51381 this.min.max( box.min );
51382 this.max.min( box.max );
51384 if ( this.isEmpty() ) this.makeEmpty();
51392 this.min.min( box.min );
51393 this.max.max( box.max );
51399 translate( offset ) {
51401 this.min.add( offset );
51402 this.max.add( offset );
51410 return box.min.equals( this.min ) && box.max.equals( this.max );
51416 const _startP = /*@__PURE__*/ new Vector3();
51417 const _startEnd = /*@__PURE__*/ new Vector3();
51421 constructor( start = new Vector3(), end = new Vector3() ) {
51423 this.start = start;
51428 set( start, end ) {
51430 this.start.copy( start );
51431 this.end.copy( end );
51439 this.start.copy( line.start );
51440 this.end.copy( line.end );
51446 getCenter( target ) {
51448 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 );
51454 return target.subVectors( this.end, this.start );
51460 return this.start.distanceToSquared( this.end );
51466 return this.start.distanceTo( this.end );
51472 return this.delta( target ).multiplyScalar( t ).add( this.start );
51476 closestPointToPointParameter( point, clampToLine ) {
51478 _startP.subVectors( point, this.start );
51479 _startEnd.subVectors( this.end, this.start );
51481 const startEnd2 = _startEnd.dot( _startEnd );
51482 const startEnd_startP = _startEnd.dot( _startP );
51484 let t = startEnd_startP / startEnd2;
51486 if ( clampToLine ) {
51488 t = clamp( t, 0, 1 );
51496 closestPointToPoint( point, clampToLine, target ) {
51498 const t = this.closestPointToPointParameter( point, clampToLine );
51500 return this.delta( target ).multiplyScalar( t ).add( this.start );
51504 applyMatrix4( matrix ) {
51506 this.start.applyMatrix4( matrix );
51507 this.end.applyMatrix4( matrix );
51515 return line.start.equals( this.start ) && line.end.equals( this.end );
51521 return new this.constructor().copy( this );
51527 const _vector$3 = /*@__PURE__*/ new Vector3();
51529 class SpotLightHelper extends Object3D {
51531 constructor( light, color ) {
51535 this.light = light;
51537 this.matrix = light.matrixWorld;
51538 this.matrixAutoUpdate = false;
51540 this.color = color;
51542 this.type = 'SpotLightHelper';
51544 const geometry = new BufferGeometry();
51546 const positions = [
51549 0, 0, 0, - 1, 0, 1,
51554 for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) {
51556 const p1 = ( i / l ) * Math.PI * 2;
51557 const p2 = ( j / l ) * Math.PI * 2;
51560 Math.cos( p1 ), Math.sin( p1 ), 1,
51561 Math.cos( p2 ), Math.sin( p2 ), 1
51566 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
51568 const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
51570 this.cone = new LineSegments( geometry, material );
51571 this.add( this.cone );
51579 this.cone.geometry.dispose();
51580 this.cone.material.dispose();
51586 this.light.updateWorldMatrix( true, false );
51587 this.light.target.updateWorldMatrix( true, false );
51589 const coneLength = this.light.distance ? this.light.distance : 1000;
51590 const coneWidth = coneLength * Math.tan( this.light.angle );
51592 this.cone.scale.set( coneWidth, coneWidth, coneLength );
51594 _vector$3.setFromMatrixPosition( this.light.target.matrixWorld );
51596 this.cone.lookAt( _vector$3 );
51598 if ( this.color !== undefined ) {
51600 this.cone.material.color.set( this.color );
51604 this.cone.material.color.copy( this.light.color );
51612 const _vector$2 = /*@__PURE__*/ new Vector3();
51613 const _boneMatrix = /*@__PURE__*/ new Matrix4();
51614 const _matrixWorldInv = /*@__PURE__*/ new Matrix4();
51617 class SkeletonHelper extends LineSegments {
51619 constructor( object ) {
51621 const bones = getBoneList( object );
51623 const geometry = new BufferGeometry();
51625 const vertices = [];
51628 const color1 = new Color( 0, 0, 1 );
51629 const color2 = new Color( 0, 1, 0 );
51631 for ( let i = 0; i < bones.length; i ++ ) {
51633 const bone = bones[ i ];
51635 if ( bone.parent && bone.parent.isBone ) {
51637 vertices.push( 0, 0, 0 );
51638 vertices.push( 0, 0, 0 );
51639 colors.push( color1.r, color1.g, color1.b );
51640 colors.push( color2.r, color2.g, color2.b );
51646 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
51647 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
51649 const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } );
51651 super( geometry, material );
51653 this.isSkeletonHelper = true;
51655 this.type = 'SkeletonHelper';
51657 this.root = object;
51658 this.bones = bones;
51660 this.matrix = object.matrixWorld;
51661 this.matrixAutoUpdate = false;
51665 updateMatrixWorld( force ) {
51667 const bones = this.bones;
51669 const geometry = this.geometry;
51670 const position = geometry.getAttribute( 'position' );
51672 _matrixWorldInv.copy( this.root.matrixWorld ).invert();
51674 for ( let i = 0, j = 0; i < bones.length; i ++ ) {
51676 const bone = bones[ i ];
51678 if ( bone.parent && bone.parent.isBone ) {
51680 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld );
51681 _vector$2.setFromMatrixPosition( _boneMatrix );
51682 position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z );
51684 _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld );
51685 _vector$2.setFromMatrixPosition( _boneMatrix );
51686 position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z );
51694 geometry.getAttribute( 'position' ).needsUpdate = true;
51696 super.updateMatrixWorld( force );
51702 this.geometry.dispose();
51703 this.material.dispose();
51710 function getBoneList( object ) {
51712 const boneList = [];
51714 if ( object.isBone === true ) {
51716 boneList.push( object );
51720 for ( let i = 0; i < object.children.length; i ++ ) {
51722 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) );
51730 class PointLightHelper extends Mesh {
51732 constructor( light, sphereSize, color ) {
51734 const geometry = new SphereGeometry( sphereSize, 4, 2 );
51735 const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
51737 super( geometry, material );
51739 this.light = light;
51741 this.color = color;
51743 this.type = 'PointLightHelper';
51745 this.matrix = this.light.matrixWorld;
51746 this.matrixAutoUpdate = false;
51752 // TODO: delete this comment?
51753 const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 );
51754 const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } );
51756 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial );
51757 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial );
51759 const d = light.distance;
51763 this.lightDistance.visible = false;
51767 this.lightDistance.scale.set( d, d, d );
51771 this.add( this.lightDistance );
51778 this.geometry.dispose();
51779 this.material.dispose();
51785 this.light.updateWorldMatrix( true, false );
51787 if ( this.color !== undefined ) {
51789 this.material.color.set( this.color );
51793 this.material.color.copy( this.light.color );
51798 const d = this.light.distance;
51802 this.lightDistance.visible = false;
51806 this.lightDistance.visible = true;
51807 this.lightDistance.scale.set( d, d, d );
51816 const _vector$1 = /*@__PURE__*/ new Vector3();
51817 const _color1 = /*@__PURE__*/ new Color();
51818 const _color2 = /*@__PURE__*/ new Color();
51820 class HemisphereLightHelper extends Object3D {
51822 constructor( light, size, color ) {
51826 this.light = light;
51828 this.matrix = light.matrixWorld;
51829 this.matrixAutoUpdate = false;
51831 this.color = color;
51833 this.type = 'HemisphereLightHelper';
51835 const geometry = new OctahedronGeometry( size );
51836 geometry.rotateY( Math.PI * 0.5 );
51838 this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } );
51839 if ( this.color === undefined ) this.material.vertexColors = true;
51841 const position = geometry.getAttribute( 'position' );
51842 const colors = new Float32Array( position.count * 3 );
51844 geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) );
51846 this.add( new Mesh( geometry, this.material ) );
51854 this.children[ 0 ].geometry.dispose();
51855 this.children[ 0 ].material.dispose();
51861 const mesh = this.children[ 0 ];
51863 if ( this.color !== undefined ) {
51865 this.material.color.set( this.color );
51869 const colors = mesh.geometry.getAttribute( 'color' );
51871 _color1.copy( this.light.color );
51872 _color2.copy( this.light.groundColor );
51874 for ( let i = 0, l = colors.count; i < l; i ++ ) {
51876 const color = ( i < ( l / 2 ) ) ? _color1 : _color2;
51878 colors.setXYZ( i, color.r, color.g, color.b );
51882 colors.needsUpdate = true;
51886 this.light.updateWorldMatrix( true, false );
51888 mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() );
51894 class GridHelper extends LineSegments {
51896 constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) {
51898 color1 = new Color( color1 );
51899 color2 = new Color( color2 );
51901 const center = divisions / 2;
51902 const step = size / divisions;
51903 const halfSize = size / 2;
51905 const vertices = [], colors = [];
51907 for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) {
51909 vertices.push( - halfSize, 0, k, halfSize, 0, k );
51910 vertices.push( k, 0, - halfSize, k, 0, halfSize );
51912 const color = i === center ? color1 : color2;
51914 color.toArray( colors, j ); j += 3;
51915 color.toArray( colors, j ); j += 3;
51916 color.toArray( colors, j ); j += 3;
51917 color.toArray( colors, j ); j += 3;
51921 const geometry = new BufferGeometry();
51922 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
51923 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
51925 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
51927 super( geometry, material );
51929 this.type = 'GridHelper';
51935 this.geometry.dispose();
51936 this.material.dispose();
51942 class PolarGridHelper extends LineSegments {
51944 constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) {
51946 color1 = new Color( color1 );
51947 color2 = new Color( color2 );
51949 const vertices = [];
51952 // create the sectors
51954 if ( sectors > 1 ) {
51956 for ( let i = 0; i < sectors; i ++ ) {
51958 const v = ( i / sectors ) * ( Math.PI * 2 );
51960 const x = Math.sin( v ) * radius;
51961 const z = Math.cos( v ) * radius;
51963 vertices.push( 0, 0, 0 );
51964 vertices.push( x, 0, z );
51966 const color = ( i & 1 ) ? color1 : color2;
51968 colors.push( color.r, color.g, color.b );
51969 colors.push( color.r, color.g, color.b );
51975 // create the rings
51977 for ( let i = 0; i < rings; i ++ ) {
51979 const color = ( i & 1 ) ? color1 : color2;
51981 const r = radius - ( radius / rings * i );
51983 for ( let j = 0; j < divisions; j ++ ) {
51987 let v = ( j / divisions ) * ( Math.PI * 2 );
51989 let x = Math.sin( v ) * r;
51990 let z = Math.cos( v ) * r;
51992 vertices.push( x, 0, z );
51993 colors.push( color.r, color.g, color.b );
51997 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 );
51999 x = Math.sin( v ) * r;
52000 z = Math.cos( v ) * r;
52002 vertices.push( x, 0, z );
52003 colors.push( color.r, color.g, color.b );
52009 const geometry = new BufferGeometry();
52010 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52011 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52013 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
52015 super( geometry, material );
52017 this.type = 'PolarGridHelper';
52023 this.geometry.dispose();
52024 this.material.dispose();
52030 const _v1 = /*@__PURE__*/ new Vector3();
52031 const _v2 = /*@__PURE__*/ new Vector3();
52032 const _v3 = /*@__PURE__*/ new Vector3();
52034 class DirectionalLightHelper extends Object3D {
52036 constructor( light, size, color ) {
52040 this.light = light;
52042 this.matrix = light.matrixWorld;
52043 this.matrixAutoUpdate = false;
52045 this.color = color;
52047 this.type = 'DirectionalLightHelper';
52049 if ( size === undefined ) size = 1;
52051 let geometry = new BufferGeometry();
52052 geometry.setAttribute( 'position', new Float32BufferAttribute( [
52060 const material = new LineBasicMaterial( { fog: false, toneMapped: false } );
52062 this.lightPlane = new Line( geometry, material );
52063 this.add( this.lightPlane );
52065 geometry = new BufferGeometry();
52066 geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) );
52068 this.targetLine = new Line( geometry, material );
52069 this.add( this.targetLine );
52077 this.lightPlane.geometry.dispose();
52078 this.lightPlane.material.dispose();
52079 this.targetLine.geometry.dispose();
52080 this.targetLine.material.dispose();
52086 this.light.updateWorldMatrix( true, false );
52087 this.light.target.updateWorldMatrix( true, false );
52089 _v1.setFromMatrixPosition( this.light.matrixWorld );
52090 _v2.setFromMatrixPosition( this.light.target.matrixWorld );
52091 _v3.subVectors( _v2, _v1 );
52093 this.lightPlane.lookAt( _v2 );
52095 if ( this.color !== undefined ) {
52097 this.lightPlane.material.color.set( this.color );
52098 this.targetLine.material.color.set( this.color );
52102 this.lightPlane.material.color.copy( this.light.color );
52103 this.targetLine.material.color.copy( this.light.color );
52107 this.targetLine.lookAt( _v2 );
52108 this.targetLine.scale.z = _v3.length();
52114 const _vector = /*@__PURE__*/ new Vector3();
52115 const _camera = /*@__PURE__*/ new Camera();
52124 class CameraHelper extends LineSegments {
52126 constructor( camera ) {
52128 const geometry = new BufferGeometry();
52129 const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } );
52131 const vertices = [];
52134 const pointMap = {};
52138 addLine( 'n1', 'n2' );
52139 addLine( 'n2', 'n4' );
52140 addLine( 'n4', 'n3' );
52141 addLine( 'n3', 'n1' );
52145 addLine( 'f1', 'f2' );
52146 addLine( 'f2', 'f4' );
52147 addLine( 'f4', 'f3' );
52148 addLine( 'f3', 'f1' );
52152 addLine( 'n1', 'f1' );
52153 addLine( 'n2', 'f2' );
52154 addLine( 'n3', 'f3' );
52155 addLine( 'n4', 'f4' );
52159 addLine( 'p', 'n1' );
52160 addLine( 'p', 'n2' );
52161 addLine( 'p', 'n3' );
52162 addLine( 'p', 'n4' );
52166 addLine( 'u1', 'u2' );
52167 addLine( 'u2', 'u3' );
52168 addLine( 'u3', 'u1' );
52172 addLine( 'c', 't' );
52173 addLine( 'p', 'c' );
52177 addLine( 'cn1', 'cn2' );
52178 addLine( 'cn3', 'cn4' );
52180 addLine( 'cf1', 'cf2' );
52181 addLine( 'cf3', 'cf4' );
52183 function addLine( a, b ) {
52190 function addPoint( id ) {
52192 vertices.push( 0, 0, 0 );
52193 colors.push( 0, 0, 0 );
52195 if ( pointMap[ id ] === undefined ) {
52197 pointMap[ id ] = [];
52201 pointMap[ id ].push( ( vertices.length / 3 ) - 1 );
52205 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52206 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52208 super( geometry, material );
52210 this.type = 'CameraHelper';
52212 this.camera = camera;
52213 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix();
52215 this.matrix = camera.matrixWorld;
52216 this.matrixAutoUpdate = false;
52218 this.pointMap = pointMap;
52224 const colorFrustum = new Color( 0xffaa00 );
52225 const colorCone = new Color( 0xff0000 );
52226 const colorUp = new Color( 0x00aaff );
52227 const colorTarget = new Color( 0xffffff );
52228 const colorCross = new Color( 0x333333 );
52230 this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross );
52234 setColors( frustum, cone, up, target, cross ) {
52236 const geometry = this.geometry;
52238 const colorAttribute = geometry.getAttribute( 'color' );
52242 colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2
52243 colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4
52244 colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3
52245 colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1
52249 colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2
52250 colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4
52251 colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3
52252 colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1
52256 colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1
52257 colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2
52258 colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3
52259 colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4
52263 colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1
52264 colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2
52265 colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3
52266 colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4
52270 colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2
52271 colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3
52272 colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1
52276 colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t
52277 colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c
52281 colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2
52282 colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4
52284 colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2
52285 colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4
52287 colorAttribute.needsUpdate = true;
52293 const geometry = this.geometry;
52294 const pointMap = this.pointMap;
52296 const w = 1, h = 1;
52298 // we need just camera projection matrix inverse
52299 // world matrix must be identity
52301 _camera.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse );
52305 setPoint( 'c', pointMap, geometry, _camera, 0, 0, - 1 );
52306 setPoint( 't', pointMap, geometry, _camera, 0, 0, 1 );
52310 setPoint( 'n1', pointMap, geometry, _camera, - w, - h, - 1 );
52311 setPoint( 'n2', pointMap, geometry, _camera, w, - h, - 1 );
52312 setPoint( 'n3', pointMap, geometry, _camera, - w, h, - 1 );
52313 setPoint( 'n4', pointMap, geometry, _camera, w, h, - 1 );
52317 setPoint( 'f1', pointMap, geometry, _camera, - w, - h, 1 );
52318 setPoint( 'f2', pointMap, geometry, _camera, w, - h, 1 );
52319 setPoint( 'f3', pointMap, geometry, _camera, - w, h, 1 );
52320 setPoint( 'f4', pointMap, geometry, _camera, w, h, 1 );
52324 setPoint( 'u1', pointMap, geometry, _camera, w * 0.7, h * 1.1, - 1 );
52325 setPoint( 'u2', pointMap, geometry, _camera, - w * 0.7, h * 1.1, - 1 );
52326 setPoint( 'u3', pointMap, geometry, _camera, 0, h * 2, - 1 );
52330 setPoint( 'cf1', pointMap, geometry, _camera, - w, 0, 1 );
52331 setPoint( 'cf2', pointMap, geometry, _camera, w, 0, 1 );
52332 setPoint( 'cf3', pointMap, geometry, _camera, 0, - h, 1 );
52333 setPoint( 'cf4', pointMap, geometry, _camera, 0, h, 1 );
52335 setPoint( 'cn1', pointMap, geometry, _camera, - w, 0, - 1 );
52336 setPoint( 'cn2', pointMap, geometry, _camera, w, 0, - 1 );
52337 setPoint( 'cn3', pointMap, geometry, _camera, 0, - h, - 1 );
52338 setPoint( 'cn4', pointMap, geometry, _camera, 0, h, - 1 );
52340 geometry.getAttribute( 'position' ).needsUpdate = true;
52346 this.geometry.dispose();
52347 this.material.dispose();
52354 function setPoint( point, pointMap, geometry, camera, x, y, z ) {
52356 _vector.set( x, y, z ).unproject( camera );
52358 const points = pointMap[ point ];
52360 if ( points !== undefined ) {
52362 const position = geometry.getAttribute( 'position' );
52364 for ( let i = 0, l = points.length; i < l; i ++ ) {
52366 position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z );
52374 const _box = /*@__PURE__*/ new Box3();
52376 class BoxHelper extends LineSegments {
52378 constructor( object, color = 0xffff00 ) {
52380 const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
52381 const positions = new Float32Array( 8 * 3 );
52383 const geometry = new BufferGeometry();
52384 geometry.setIndex( new BufferAttribute( indices, 1 ) );
52385 geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) );
52387 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52389 this.object = object;
52390 this.type = 'BoxHelper';
52392 this.matrixAutoUpdate = false;
52400 if ( object !== undefined ) {
52402 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
52406 if ( this.object !== undefined ) {
52408 _box.setFromObject( this.object );
52412 if ( _box.isEmpty() ) return;
52414 const min = _box.min;
52415 const max = _box.max;
52423 0: max.x, max.y, max.z
52424 1: min.x, max.y, max.z
52425 2: min.x, min.y, max.z
52426 3: max.x, min.y, max.z
52427 4: max.x, max.y, min.z
52428 5: min.x, max.y, min.z
52429 6: min.x, min.y, min.z
52430 7: max.x, min.y, min.z
52433 const position = this.geometry.attributes.position;
52434 const array = position.array;
52436 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z;
52437 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z;
52438 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z;
52439 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z;
52440 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z;
52441 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z;
52442 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z;
52443 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z;
52445 position.needsUpdate = true;
52447 this.geometry.computeBoundingSphere();
52451 setFromObject( object ) {
52453 this.object = object;
52460 copy( source, recursive ) {
52462 super.copy( source, recursive );
52464 this.object = source.object;
52472 this.geometry.dispose();
52473 this.material.dispose();
52479 class Box3Helper extends LineSegments {
52481 constructor( box, color = 0xffff00 ) {
52483 const indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
52485 const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ];
52487 const geometry = new BufferGeometry();
52489 geometry.setIndex( new BufferAttribute( indices, 1 ) );
52491 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
52493 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52497 this.type = 'Box3Helper';
52499 this.geometry.computeBoundingSphere();
52503 updateMatrixWorld( force ) {
52505 const box = this.box;
52507 if ( box.isEmpty() ) return;
52509 box.getCenter( this.position );
52511 box.getSize( this.scale );
52513 this.scale.multiplyScalar( 0.5 );
52515 super.updateMatrixWorld( force );
52521 this.geometry.dispose();
52522 this.material.dispose();
52528 class PlaneHelper extends Line {
52530 constructor( plane, size = 1, hex = 0xffff00 ) {
52534 const positions = [ 1, - 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ];
52536 const geometry = new BufferGeometry();
52537 geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) );
52538 geometry.computeBoundingSphere();
52540 super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52542 this.type = 'PlaneHelper';
52544 this.plane = plane;
52548 const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ];
52550 const geometry2 = new BufferGeometry();
52551 geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) );
52552 geometry2.computeBoundingSphere();
52554 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) );
52558 updateMatrixWorld( force ) {
52560 this.position.set( 0, 0, 0 );
52562 this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 );
52564 this.lookAt( this.plane.normal );
52566 this.translateZ( - this.plane.constant );
52568 super.updateMatrixWorld( force );
52574 this.geometry.dispose();
52575 this.material.dispose();
52576 this.children[ 0 ].geometry.dispose();
52577 this.children[ 0 ].material.dispose();
52583 const _axis = /*@__PURE__*/ new Vector3();
52584 let _lineGeometry, _coneGeometry;
52586 class ArrowHelper extends Object3D {
52588 // dir is assumed to be normalized
52590 constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) {
52594 this.type = 'ArrowHelper';
52596 if ( _lineGeometry === undefined ) {
52598 _lineGeometry = new BufferGeometry();
52599 _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) );
52601 _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 );
52602 _coneGeometry.translate( 0, - 0.5, 0 );
52606 this.position.copy( origin );
52608 this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) );
52609 this.line.matrixAutoUpdate = false;
52610 this.add( this.line );
52612 this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) );
52613 this.cone.matrixAutoUpdate = false;
52614 this.add( this.cone );
52616 this.setDirection( dir );
52617 this.setLength( length, headLength, headWidth );
52621 setDirection( dir ) {
52623 // dir is assumed to be normalized
52625 if ( dir.y > 0.99999 ) {
52627 this.quaternion.set( 0, 0, 0, 1 );
52629 } else if ( dir.y < - 0.99999 ) {
52631 this.quaternion.set( 1, 0, 0, 0 );
52635 _axis.set( dir.z, 0, - dir.x ).normalize();
52637 const radians = Math.acos( dir.y );
52639 this.quaternion.setFromAxisAngle( _axis, radians );
52645 setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) {
52647 this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
52648 this.line.updateMatrix();
52650 this.cone.scale.set( headWidth, headLength, headWidth );
52651 this.cone.position.y = length;
52652 this.cone.updateMatrix();
52656 setColor( color ) {
52658 this.line.material.color.set( color );
52659 this.cone.material.color.set( color );
52665 super.copy( source, false );
52667 this.line.copy( source.line );
52668 this.cone.copy( source.cone );
52676 this.line.geometry.dispose();
52677 this.line.material.dispose();
52678 this.cone.geometry.dispose();
52679 this.cone.material.dispose();
52685 class AxesHelper extends LineSegments {
52687 constructor( size = 1 ) {
52690 0, 0, 0, size, 0, 0,
52691 0, 0, 0, 0, size, 0,
52692 0, 0, 0, 0, 0, size
52696 1, 0, 0, 1, 0.6, 0,
52697 0, 1, 0, 0.6, 1, 0,
52701 const geometry = new BufferGeometry();
52702 geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
52703 geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) );
52705 const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } );
52707 super( geometry, material );
52709 this.type = 'AxesHelper';
52713 setColors( xAxisColor, yAxisColor, zAxisColor ) {
52715 const color = new Color();
52716 const array = this.geometry.attributes.color.array;
52718 color.set( xAxisColor );
52719 color.toArray( array, 0 );
52720 color.toArray( array, 3 );
52722 color.set( yAxisColor );
52723 color.toArray( array, 6 );
52724 color.toArray( array, 9 );
52726 color.set( zAxisColor );
52727 color.toArray( array, 12 );
52728 color.toArray( array, 15 );
52730 this.geometry.attributes.color.needsUpdate = true;
52738 this.geometry.dispose();
52739 this.material.dispose();
52749 this.type = 'ShapePath';
52751 this.color = new Color();
52753 this.subPaths = [];
52754 this.currentPath = null;
52760 this.currentPath = new Path();
52761 this.subPaths.push( this.currentPath );
52762 this.currentPath.moveTo( x, y );
52770 this.currentPath.lineTo( x, y );
52776 quadraticCurveTo( aCPx, aCPy, aX, aY ) {
52778 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY );
52784 bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
52786 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY );
52792 splineThru( pts ) {
52794 this.currentPath.splineThru( pts );
52800 toShapes( isCCW ) {
52802 function toShapesNoHoles( inSubpaths ) {
52806 for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) {
52808 const tmpPath = inSubpaths[ i ];
52810 const tmpShape = new Shape();
52811 tmpShape.curves = tmpPath.curves;
52813 shapes.push( tmpShape );
52821 function isPointInsidePolygon( inPt, inPolygon ) {
52823 const polyLen = inPolygon.length;
52825 // inPt on polygon contour => immediate success or
52826 // toggling of inside/outside at every single! intersection point of an edge
52827 // with the horizontal line through inPt, left of inPt
52828 // not counting lowerY endpoints of edges and whole edges on that line
52829 let inside = false;
52830 for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
52832 let edgeLowPt = inPolygon[ p ];
52833 let edgeHighPt = inPolygon[ q ];
52835 let edgeDx = edgeHighPt.x - edgeLowPt.x;
52836 let edgeDy = edgeHighPt.y - edgeLowPt.y;
52838 if ( Math.abs( edgeDy ) > Number.EPSILON ) {
52841 if ( edgeDy < 0 ) {
52843 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
52844 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
52848 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
52850 if ( inPt.y === edgeLowPt.y ) {
52852 if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ?
52853 // continue; // no intersection or edgeLowPt => doesn't count !!!
52857 const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
52858 if ( perpEdge === 0 ) return true; // inPt is on contour ?
52859 if ( perpEdge < 0 ) continue;
52860 inside = ! inside; // true intersection left of inPt
52866 // parallel or collinear
52867 if ( inPt.y !== edgeLowPt.y ) continue; // parallel
52868 // edge lies on the same horizontal line as inPt
52869 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
52870 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
52881 const isClockWise = ShapeUtils.isClockWise;
52883 const subPaths = this.subPaths;
52884 if ( subPaths.length === 0 ) return [];
52886 let solid, tmpPath, tmpShape;
52889 if ( subPaths.length === 1 ) {
52891 tmpPath = subPaths[ 0 ];
52892 tmpShape = new Shape();
52893 tmpShape.curves = tmpPath.curves;
52894 shapes.push( tmpShape );
52899 let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
52900 holesFirst = isCCW ? ! holesFirst : holesFirst;
52902 // console.log("Holes first
", holesFirst);
52904 const betterShapeHoles = [];
52905 const newShapes = [];
52906 let newShapeHoles = [];
52910 newShapes[ mainIdx ] = undefined;
52911 newShapeHoles[ mainIdx ] = [];
52913 for ( let i = 0, l = subPaths.length; i < l; i ++ ) {
52915 tmpPath = subPaths[ i ];
52916 tmpPoints = tmpPath.getPoints();
52917 solid = isClockWise( tmpPoints );
52918 solid = isCCW ? ! solid : solid;
52922 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++;
52924 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints };
52925 newShapes[ mainIdx ].s.curves = tmpPath.curves;
52927 if ( holesFirst ) mainIdx ++;
52928 newShapeHoles[ mainIdx ] = [];
52930 //console.log('cw', i);
52934 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
52936 //console.log('ccw', i);
52942 // only Holes? -> probably all Shapes with wrong orientation
52943 if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths );
52946 if ( newShapes.length > 1 ) {
52948 let ambiguous = false;
52951 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
52953 betterShapeHoles[ sIdx ] = [];
52957 for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
52959 const sho = newShapeHoles[ sIdx ];
52961 for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) {
52963 const ho = sho[ hIdx ];
52964 let hole_unassigned = true;
52966 for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
52968 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
52970 if ( sIdx !== s2Idx ) toChange ++;
52972 if ( hole_unassigned ) {
52974 hole_unassigned = false;
52975 betterShapeHoles[ s2Idx ].push( ho );
52987 if ( hole_unassigned ) {
52989 betterShapeHoles[ sIdx ].push( ho );
52997 if ( toChange > 0 && ambiguous === false ) {
52999 newShapeHoles = betterShapeHoles;
53007 for ( let i = 0, il = newShapes.length; i < il; i ++ ) {
53009 tmpShape = newShapes[ i ].s;
53010 shapes.push( tmpShape );
53011 tmpHoles = newShapeHoles[ i ];
53013 for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
53015 tmpShape.holes.push( tmpHoles[ j ].h );
53021 //console.log("shape
", shapes);
53029 if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
53031 __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
53032 revision: REVISION,
53037 if ( typeof window !== 'undefined' ) {
53039 if ( window.__THREE__ ) {
53041 console.warn( 'WARNING: Multiple instances of Three.js being imported.' );
53045 window.__THREE__ = REVISION;
53051 exports.ACESFilmicToneMapping = ACESFilmicToneMapping;
53052 exports.AddEquation = AddEquation;
53053 exports.AddOperation = AddOperation;
53054 exports.AdditiveAnimationBlendMode = AdditiveAnimationBlendMode;
53055 exports.AdditiveBlending = AdditiveBlending;
53056 exports.AgXToneMapping = AgXToneMapping;
53057 exports.AlphaFormat = AlphaFormat;
53058 exports.AlwaysCompare = AlwaysCompare;
53059 exports.AlwaysDepth = AlwaysDepth;
53060 exports.AlwaysStencilFunc = AlwaysStencilFunc;
53061 exports.AmbientLight = AmbientLight;
53062 exports.AnimationAction = AnimationAction;
53063 exports.AnimationClip = AnimationClip;
53064 exports.AnimationLoader = AnimationLoader;
53065 exports.AnimationMixer = AnimationMixer;
53066 exports.AnimationObjectGroup = AnimationObjectGroup;
53067 exports.AnimationUtils = AnimationUtils;
53068 exports.ArcCurve = ArcCurve;
53069 exports.ArrayCamera = ArrayCamera;
53070 exports.ArrowHelper = ArrowHelper;
53071 exports.AttachedBindMode = AttachedBindMode;
53072 exports.Audio = Audio;
53073 exports.AudioAnalyser = AudioAnalyser;
53074 exports.AudioContext = AudioContext;
53075 exports.AudioListener = AudioListener;
53076 exports.AudioLoader = AudioLoader;
53077 exports.AxesHelper = AxesHelper;
53078 exports.BackSide = BackSide;
53079 exports.BasicDepthPacking = BasicDepthPacking;
53080 exports.BasicShadowMap = BasicShadowMap;
53081 exports.BatchedMesh = BatchedMesh;
53082 exports.Bone = Bone;
53083 exports.BooleanKeyframeTrack = BooleanKeyframeTrack;
53084 exports.Box2 = Box2;
53085 exports.Box3 = Box3;
53086 exports.Box3Helper = Box3Helper;
53087 exports.BoxGeometry = BoxGeometry;
53088 exports.BoxHelper = BoxHelper;
53089 exports.BufferAttribute = BufferAttribute;
53090 exports.BufferGeometry = BufferGeometry;
53091 exports.BufferGeometryLoader = BufferGeometryLoader;
53092 exports.ByteType = ByteType;
53093 exports.Cache = Cache;
53094 exports.Camera = Camera;
53095 exports.CameraHelper = CameraHelper;
53096 exports.CanvasTexture = CanvasTexture;
53097 exports.CapsuleGeometry = CapsuleGeometry;
53098 exports.CatmullRomCurve3 = CatmullRomCurve3;
53099 exports.CineonToneMapping = CineonToneMapping;
53100 exports.CircleGeometry = CircleGeometry;
53101 exports.ClampToEdgeWrapping = ClampToEdgeWrapping;
53102 exports.Clock = Clock;
53103 exports.Color = Color;
53104 exports.ColorKeyframeTrack = ColorKeyframeTrack;
53105 exports.ColorManagement = ColorManagement;
53106 exports.CompressedArrayTexture = CompressedArrayTexture;
53107 exports.CompressedCubeTexture = CompressedCubeTexture;
53108 exports.CompressedTexture = CompressedTexture;
53109 exports.CompressedTextureLoader = CompressedTextureLoader;
53110 exports.ConeGeometry = ConeGeometry;
53111 exports.ConstantAlphaFactor = ConstantAlphaFactor;
53112 exports.ConstantColorFactor = ConstantColorFactor;
53113 exports.CubeCamera = CubeCamera;
53114 exports.CubeReflectionMapping = CubeReflectionMapping;
53115 exports.CubeRefractionMapping = CubeRefractionMapping;
53116 exports.CubeTexture = CubeTexture;
53117 exports.CubeTextureLoader = CubeTextureLoader;
53118 exports.CubeUVReflectionMapping = CubeUVReflectionMapping;
53119 exports.CubicBezierCurve = CubicBezierCurve;
53120 exports.CubicBezierCurve3 = CubicBezierCurve3;
53121 exports.CubicInterpolant = CubicInterpolant;
53122 exports.CullFaceBack = CullFaceBack;
53123 exports.CullFaceFront = CullFaceFront;
53124 exports.CullFaceFrontBack = CullFaceFrontBack;
53125 exports.CullFaceNone = CullFaceNone;
53126 exports.Curve = Curve;
53127 exports.CurvePath = CurvePath;
53128 exports.CustomBlending = CustomBlending;
53129 exports.CustomToneMapping = CustomToneMapping;
53130 exports.CylinderGeometry = CylinderGeometry;
53131 exports.Cylindrical = Cylindrical;
53132 exports.Data3DTexture = Data3DTexture;
53133 exports.DataArrayTexture = DataArrayTexture;
53134 exports.DataTexture = DataTexture;
53135 exports.DataTextureLoader = DataTextureLoader;
53136 exports.DataUtils = DataUtils;
53137 exports.DecrementStencilOp = DecrementStencilOp;
53138 exports.DecrementWrapStencilOp = DecrementWrapStencilOp;
53139 exports.DefaultLoadingManager = DefaultLoadingManager;
53140 exports.DepthFormat = DepthFormat;
53141 exports.DepthStencilFormat = DepthStencilFormat;
53142 exports.DepthTexture = DepthTexture;
53143 exports.DetachedBindMode = DetachedBindMode;
53144 exports.DirectionalLight = DirectionalLight;
53145 exports.DirectionalLightHelper = DirectionalLightHelper;
53146 exports.DiscreteInterpolant = DiscreteInterpolant;
53147 exports.DisplayP3ColorSpace = DisplayP3ColorSpace;
53148 exports.DodecahedronGeometry = DodecahedronGeometry;
53149 exports.DoubleSide = DoubleSide;
53150 exports.DstAlphaFactor = DstAlphaFactor;
53151 exports.DstColorFactor = DstColorFactor;
53152 exports.DynamicCopyUsage = DynamicCopyUsage;
53153 exports.DynamicDrawUsage = DynamicDrawUsage;
53154 exports.DynamicReadUsage = DynamicReadUsage;
53155 exports.EdgesGeometry = EdgesGeometry;
53156 exports.EllipseCurve = EllipseCurve;
53157 exports.EqualCompare = EqualCompare;
53158 exports.EqualDepth = EqualDepth;
53159 exports.EqualStencilFunc = EqualStencilFunc;
53160 exports.EquirectangularReflectionMapping = EquirectangularReflectionMapping;
53161 exports.EquirectangularRefractionMapping = EquirectangularRefractionMapping;
53162 exports.Euler = Euler;
53163 exports.EventDispatcher = EventDispatcher;
53164 exports.ExtrudeGeometry = ExtrudeGeometry;
53165 exports.FileLoader = FileLoader;
53166 exports.Float16BufferAttribute = Float16BufferAttribute;
53167 exports.Float32BufferAttribute = Float32BufferAttribute;
53168 exports.Float64BufferAttribute = Float64BufferAttribute;
53169 exports.FloatType = FloatType;
53171 exports.FogExp2 = FogExp2;
53172 exports.FramebufferTexture = FramebufferTexture;
53173 exports.FrontSide = FrontSide;
53174 exports.Frustum = Frustum;
53175 exports.GLBufferAttribute = GLBufferAttribute;
53176 exports.GLSL1 = GLSL1;
53177 exports.GLSL3 = GLSL3;
53178 exports.GreaterCompare = GreaterCompare;
53179 exports.GreaterDepth = GreaterDepth;
53180 exports.GreaterEqualCompare = GreaterEqualCompare;
53181 exports.GreaterEqualDepth = GreaterEqualDepth;
53182 exports.GreaterEqualStencilFunc = GreaterEqualStencilFunc;
53183 exports.GreaterStencilFunc = GreaterStencilFunc;
53184 exports.GridHelper = GridHelper;
53185 exports.Group = Group;
53186 exports.HalfFloatType = HalfFloatType;
53187 exports.HemisphereLight = HemisphereLight;
53188 exports.HemisphereLightHelper = HemisphereLightHelper;
53189 exports.IcosahedronGeometry = IcosahedronGeometry;
53190 exports.ImageBitmapLoader = ImageBitmapLoader;
53191 exports.ImageLoader = ImageLoader;
53192 exports.ImageUtils = ImageUtils;
53193 exports.IncrementStencilOp = IncrementStencilOp;
53194 exports.IncrementWrapStencilOp = IncrementWrapStencilOp;
53195 exports.InstancedBufferAttribute = InstancedBufferAttribute;
53196 exports.InstancedBufferGeometry = InstancedBufferGeometry;
53197 exports.InstancedInterleavedBuffer = InstancedInterleavedBuffer;
53198 exports.InstancedMesh = InstancedMesh;
53199 exports.Int16BufferAttribute = Int16BufferAttribute;
53200 exports.Int32BufferAttribute = Int32BufferAttribute;
53201 exports.Int8BufferAttribute = Int8BufferAttribute;
53202 exports.IntType = IntType;
53203 exports.InterleavedBuffer = InterleavedBuffer;
53204 exports.InterleavedBufferAttribute = InterleavedBufferAttribute;
53205 exports.Interpolant = Interpolant;
53206 exports.InterpolateDiscrete = InterpolateDiscrete;
53207 exports.InterpolateLinear = InterpolateLinear;
53208 exports.InterpolateSmooth = InterpolateSmooth;
53209 exports.InvertStencilOp = InvertStencilOp;
53210 exports.KeepStencilOp = KeepStencilOp;
53211 exports.KeyframeTrack = KeyframeTrack;
53213 exports.LatheGeometry = LatheGeometry;
53214 exports.Layers = Layers;
53215 exports.LessCompare = LessCompare;
53216 exports.LessDepth = LessDepth;
53217 exports.LessEqualCompare = LessEqualCompare;
53218 exports.LessEqualDepth = LessEqualDepth;
53219 exports.LessEqualStencilFunc = LessEqualStencilFunc;
53220 exports.LessStencilFunc = LessStencilFunc;
53221 exports.Light = Light;
53222 exports.LightProbe = LightProbe;
53223 exports.Line = Line;
53224 exports.Line3 = Line3;
53225 exports.LineBasicMaterial = LineBasicMaterial;
53226 exports.LineCurve = LineCurve;
53227 exports.LineCurve3 = LineCurve3;
53228 exports.LineDashedMaterial = LineDashedMaterial;
53229 exports.LineLoop = LineLoop;
53230 exports.LineSegments = LineSegments;
53231 exports.LinearDisplayP3ColorSpace = LinearDisplayP3ColorSpace;
53232 exports.LinearEncoding = LinearEncoding;
53233 exports.LinearFilter = LinearFilter;
53234 exports.LinearInterpolant = LinearInterpolant;
53235 exports.LinearMipMapLinearFilter = LinearMipMapLinearFilter;
53236 exports.LinearMipMapNearestFilter = LinearMipMapNearestFilter;
53237 exports.LinearMipmapLinearFilter = LinearMipmapLinearFilter;
53238 exports.LinearMipmapNearestFilter = LinearMipmapNearestFilter;
53239 exports.LinearSRGBColorSpace = LinearSRGBColorSpace;
53240 exports.LinearToneMapping = LinearToneMapping;
53241 exports.LinearTransfer = LinearTransfer;
53242 exports.Loader = Loader;
53243 exports.LoaderUtils = LoaderUtils;
53244 exports.LoadingManager = LoadingManager;
53245 exports.LoopOnce = LoopOnce;
53246 exports.LoopPingPong = LoopPingPong;
53247 exports.LoopRepeat = LoopRepeat;
53248 exports.LuminanceAlphaFormat = LuminanceAlphaFormat;
53249 exports.LuminanceFormat = LuminanceFormat;
53250 exports.MOUSE = MOUSE;
53251 exports.Material = Material;
53252 exports.MaterialLoader = MaterialLoader;
53253 exports.MathUtils = MathUtils;
53254 exports.Matrix3 = Matrix3;
53255 exports.Matrix4 = Matrix4;
53256 exports.MaxEquation = MaxEquation;
53257 exports.Mesh = Mesh;
53258 exports.MeshBasicMaterial = MeshBasicMaterial;
53259 exports.MeshDepthMaterial = MeshDepthMaterial;
53260 exports.MeshDistanceMaterial = MeshDistanceMaterial;
53261 exports.MeshLambertMaterial = MeshLambertMaterial;
53262 exports.MeshMatcapMaterial = MeshMatcapMaterial;
53263 exports.MeshNormalMaterial = MeshNormalMaterial;
53264 exports.MeshPhongMaterial = MeshPhongMaterial;
53265 exports.MeshPhysicalMaterial = MeshPhysicalMaterial;
53266 exports.MeshStandardMaterial = MeshStandardMaterial;
53267 exports.MeshToonMaterial = MeshToonMaterial;
53268 exports.MinEquation = MinEquation;
53269 exports.MirroredRepeatWrapping = MirroredRepeatWrapping;
53270 exports.MixOperation = MixOperation;
53271 exports.MultiplyBlending = MultiplyBlending;
53272 exports.MultiplyOperation = MultiplyOperation;
53273 exports.NearestFilter = NearestFilter;
53274 exports.NearestMipMapLinearFilter = NearestMipMapLinearFilter;
53275 exports.NearestMipMapNearestFilter = NearestMipMapNearestFilter;
53276 exports.NearestMipmapLinearFilter = NearestMipmapLinearFilter;
53277 exports.NearestMipmapNearestFilter = NearestMipmapNearestFilter;
53278 exports.NeverCompare = NeverCompare;
53279 exports.NeverDepth = NeverDepth;
53280 exports.NeverStencilFunc = NeverStencilFunc;
53281 exports.NoBlending = NoBlending;
53282 exports.NoColorSpace = NoColorSpace;
53283 exports.NoToneMapping = NoToneMapping;
53284 exports.NormalAnimationBlendMode = NormalAnimationBlendMode;
53285 exports.NormalBlending = NormalBlending;
53286 exports.NotEqualCompare = NotEqualCompare;
53287 exports.NotEqualDepth = NotEqualDepth;
53288 exports.NotEqualStencilFunc = NotEqualStencilFunc;
53289 exports.NumberKeyframeTrack = NumberKeyframeTrack;
53290 exports.Object3D = Object3D;
53291 exports.ObjectLoader = ObjectLoader;
53292 exports.ObjectSpaceNormalMap = ObjectSpaceNormalMap;
53293 exports.OctahedronGeometry = OctahedronGeometry;
53294 exports.OneFactor = OneFactor;
53295 exports.OneMinusConstantAlphaFactor = OneMinusConstantAlphaFactor;
53296 exports.OneMinusConstantColorFactor = OneMinusConstantColorFactor;
53297 exports.OneMinusDstAlphaFactor = OneMinusDstAlphaFactor;
53298 exports.OneMinusDstColorFactor = OneMinusDstColorFactor;
53299 exports.OneMinusSrcAlphaFactor = OneMinusSrcAlphaFactor;
53300 exports.OneMinusSrcColorFactor = OneMinusSrcColorFactor;
53301 exports.OrthographicCamera = OrthographicCamera;
53302 exports.P3Primaries = P3Primaries;
53303 exports.PCFShadowMap = PCFShadowMap;
53304 exports.PCFSoftShadowMap = PCFSoftShadowMap;
53305 exports.PMREMGenerator = PMREMGenerator;
53306 exports.Path = Path;
53307 exports.PerspectiveCamera = PerspectiveCamera;
53308 exports.Plane = Plane;
53309 exports.PlaneGeometry = PlaneGeometry;
53310 exports.PlaneHelper = PlaneHelper;
53311 exports.PointLight = PointLight;
53312 exports.PointLightHelper = PointLightHelper;
53313 exports.Points = Points;
53314 exports.PointsMaterial = PointsMaterial;
53315 exports.PolarGridHelper = PolarGridHelper;
53316 exports.PolyhedronGeometry = PolyhedronGeometry;
53317 exports.PositionalAudio = PositionalAudio;
53318 exports.PropertyBinding = PropertyBinding;
53319 exports.PropertyMixer = PropertyMixer;
53320 exports.QuadraticBezierCurve = QuadraticBezierCurve;
53321 exports.QuadraticBezierCurve3 = QuadraticBezierCurve3;
53322 exports.Quaternion = Quaternion;
53323 exports.QuaternionKeyframeTrack = QuaternionKeyframeTrack;
53324 exports.QuaternionLinearInterpolant = QuaternionLinearInterpolant;
53325 exports.RED_GREEN_RGTC2_Format = RED_GREEN_RGTC2_Format;
53326 exports.RED_RGTC1_Format = RED_RGTC1_Format;
53327 exports.REVISION = REVISION;
53328 exports.RGBADepthPacking = RGBADepthPacking;
53329 exports.RGBAFormat = RGBAFormat;
53330 exports.RGBAIntegerFormat = RGBAIntegerFormat;
53331 exports.RGBA_ASTC_10x10_Format = RGBA_ASTC_10x10_Format;
53332 exports.RGBA_ASTC_10x5_Format = RGBA_ASTC_10x5_Format;
53333 exports.RGBA_ASTC_10x6_Format = RGBA_ASTC_10x6_Format;
53334 exports.RGBA_ASTC_10x8_Format = RGBA_ASTC_10x8_Format;
53335 exports.RGBA_ASTC_12x10_Format = RGBA_ASTC_12x10_Format;
53336 exports.RGBA_ASTC_12x12_Format = RGBA_ASTC_12x12_Format;
53337 exports.RGBA_ASTC_4x4_Format = RGBA_ASTC_4x4_Format;
53338 exports.RGBA_ASTC_5x4_Format = RGBA_ASTC_5x4_Format;
53339 exports.RGBA_ASTC_5x5_Format = RGBA_ASTC_5x5_Format;
53340 exports.RGBA_ASTC_6x5_Format = RGBA_ASTC_6x5_Format;
53341 exports.RGBA_ASTC_6x6_Format = RGBA_ASTC_6x6_Format;
53342 exports.RGBA_ASTC_8x5_Format = RGBA_ASTC_8x5_Format;
53343 exports.RGBA_ASTC_8x6_Format = RGBA_ASTC_8x6_Format;
53344 exports.RGBA_ASTC_8x8_Format = RGBA_ASTC_8x8_Format;
53345 exports.RGBA_BPTC_Format = RGBA_BPTC_Format;
53346 exports.RGBA_ETC2_EAC_Format = RGBA_ETC2_EAC_Format;
53347 exports.RGBA_PVRTC_2BPPV1_Format = RGBA_PVRTC_2BPPV1_Format;
53348 exports.RGBA_PVRTC_4BPPV1_Format = RGBA_PVRTC_4BPPV1_Format;
53349 exports.RGBA_S3TC_DXT1_Format = RGBA_S3TC_DXT1_Format;
53350 exports.RGBA_S3TC_DXT3_Format = RGBA_S3TC_DXT3_Format;
53351 exports.RGBA_S3TC_DXT5_Format = RGBA_S3TC_DXT5_Format;
53352 exports.RGB_BPTC_SIGNED_Format = RGB_BPTC_SIGNED_Format;
53353 exports.RGB_BPTC_UNSIGNED_Format = RGB_BPTC_UNSIGNED_Format;
53354 exports.RGB_ETC1_Format = RGB_ETC1_Format;
53355 exports.RGB_ETC2_Format = RGB_ETC2_Format;
53356 exports.RGB_PVRTC_2BPPV1_Format = RGB_PVRTC_2BPPV1_Format;
53357 exports.RGB_PVRTC_4BPPV1_Format = RGB_PVRTC_4BPPV1_Format;
53358 exports.RGB_S3TC_DXT1_Format = RGB_S3TC_DXT1_Format;
53359 exports.RGFormat = RGFormat;
53360 exports.RGIntegerFormat = RGIntegerFormat;
53361 exports.RawShaderMaterial = RawShaderMaterial;
53363 exports.Raycaster = Raycaster;
53364 exports.Rec709Primaries = Rec709Primaries;
53365 exports.RectAreaLight = RectAreaLight;
53366 exports.RedFormat = RedFormat;
53367 exports.RedIntegerFormat = RedIntegerFormat;
53368 exports.ReinhardToneMapping = ReinhardToneMapping;
53369 exports.RenderTarget = RenderTarget;
53370 exports.RepeatWrapping = RepeatWrapping;
53371 exports.ReplaceStencilOp = ReplaceStencilOp;
53372 exports.ReverseSubtractEquation = ReverseSubtractEquation;
53373 exports.RingGeometry = RingGeometry;
53374 exports.SIGNED_RED_GREEN_RGTC2_Format = SIGNED_RED_GREEN_RGTC2_Format;
53375 exports.SIGNED_RED_RGTC1_Format = SIGNED_RED_RGTC1_Format;
53376 exports.SRGBColorSpace = SRGBColorSpace;
53377 exports.SRGBTransfer = SRGBTransfer;
53378 exports.Scene = Scene;
53379 exports.ShaderChunk = ShaderChunk;
53380 exports.ShaderLib = ShaderLib;
53381 exports.ShaderMaterial = ShaderMaterial;
53382 exports.ShadowMaterial = ShadowMaterial;
53383 exports.Shape = Shape;
53384 exports.ShapeGeometry = ShapeGeometry;
53385 exports.ShapePath = ShapePath;
53386 exports.ShapeUtils = ShapeUtils;
53387 exports.ShortType = ShortType;
53388 exports.Skeleton = Skeleton;
53389 exports.SkeletonHelper = SkeletonHelper;
53390 exports.SkinnedMesh = SkinnedMesh;
53391 exports.Source = Source;
53392 exports.Sphere = Sphere;
53393 exports.SphereGeometry = SphereGeometry;
53394 exports.Spherical = Spherical;
53395 exports.SphericalHarmonics3 = SphericalHarmonics3;
53396 exports.SplineCurve = SplineCurve;
53397 exports.SpotLight = SpotLight;
53398 exports.SpotLightHelper = SpotLightHelper;
53399 exports.Sprite = Sprite;
53400 exports.SpriteMaterial = SpriteMaterial;
53401 exports.SrcAlphaFactor = SrcAlphaFactor;
53402 exports.SrcAlphaSaturateFactor = SrcAlphaSaturateFactor;
53403 exports.SrcColorFactor = SrcColorFactor;
53404 exports.StaticCopyUsage = StaticCopyUsage;
53405 exports.StaticDrawUsage = StaticDrawUsage;
53406 exports.StaticReadUsage = StaticReadUsage;
53407 exports.StereoCamera = StereoCamera;
53408 exports.StreamCopyUsage = StreamCopyUsage;
53409 exports.StreamDrawUsage = StreamDrawUsage;
53410 exports.StreamReadUsage = StreamReadUsage;
53411 exports.StringKeyframeTrack = StringKeyframeTrack;
53412 exports.SubtractEquation = SubtractEquation;
53413 exports.SubtractiveBlending = SubtractiveBlending;
53414 exports.TOUCH = TOUCH;
53415 exports.TangentSpaceNormalMap = TangentSpaceNormalMap;
53416 exports.TetrahedronGeometry = TetrahedronGeometry;
53417 exports.Texture = Texture;
53418 exports.TextureLoader = TextureLoader;
53419 exports.TorusGeometry = TorusGeometry;
53420 exports.TorusKnotGeometry = TorusKnotGeometry;
53421 exports.Triangle = Triangle;
53422 exports.TriangleFanDrawMode = TriangleFanDrawMode;
53423 exports.TriangleStripDrawMode = TriangleStripDrawMode;
53424 exports.TrianglesDrawMode = TrianglesDrawMode;
53425 exports.TubeGeometry = TubeGeometry;
53426 exports.TwoPassDoubleSide = TwoPassDoubleSide;
53427 exports.UVMapping = UVMapping;
53428 exports.Uint16BufferAttribute = Uint16BufferAttribute;
53429 exports.Uint32BufferAttribute = Uint32BufferAttribute;
53430 exports.Uint8BufferAttribute = Uint8BufferAttribute;
53431 exports.Uint8ClampedBufferAttribute = Uint8ClampedBufferAttribute;
53432 exports.Uniform = Uniform;
53433 exports.UniformsGroup = UniformsGroup;
53434 exports.UniformsLib = UniformsLib;
53435 exports.UniformsUtils = UniformsUtils;
53436 exports.UnsignedByteType = UnsignedByteType;
53437 exports.UnsignedInt248Type = UnsignedInt248Type;
53438 exports.UnsignedIntType = UnsignedIntType;
53439 exports.UnsignedShort4444Type = UnsignedShort4444Type;
53440 exports.UnsignedShort5551Type = UnsignedShort5551Type;
53441 exports.UnsignedShortType = UnsignedShortType;
53442 exports.VSMShadowMap = VSMShadowMap;
53443 exports.Vector2 = Vector2;
53444 exports.Vector3 = Vector3;
53445 exports.Vector4 = Vector4;
53446 exports.VectorKeyframeTrack = VectorKeyframeTrack;
53447 exports.VideoTexture = VideoTexture;
53448 exports.WebGL1Renderer = WebGL1Renderer;
53449 exports.WebGL3DRenderTarget = WebGL3DRenderTarget;
53450 exports.WebGLArrayRenderTarget = WebGLArrayRenderTarget;
53451 exports.WebGLCoordinateSystem = WebGLCoordinateSystem;
53452 exports.WebGLCubeRenderTarget = WebGLCubeRenderTarget;
53453 exports.WebGLMultipleRenderTargets = WebGLMultipleRenderTargets;
53454 exports.WebGLRenderTarget = WebGLRenderTarget;
53455 exports.WebGLRenderer = WebGLRenderer;
53456 exports.WebGLUtils = WebGLUtils;
53457 exports.WebGPUCoordinateSystem = WebGPUCoordinateSystem;
53458 exports.WireframeGeometry = WireframeGeometry;
53459 exports.WrapAroundEnding = WrapAroundEnding;
53460 exports.ZeroCurvatureEnding = ZeroCurvatureEnding;
53461 exports.ZeroFactor = ZeroFactor;
53462 exports.ZeroSlopeEnding = ZeroSlopeEnding;
53463 exports.ZeroStencilOp = ZeroStencilOp;
53464 exports._SRGBAFormat = _SRGBAFormat;
53465 exports.createCanvasElement = createCanvasElement;
53466 exports.sRGBEncoding = sRGBEncoding;
OpenLayers Projection transform
OpenLayers Util getParameters
OpenLayers Protocol Response
OpenLayers Bounds fromArray
OpenLayers Layer Google cache
OpenLayers INCHES_PER_UNIT degrees
OpenLayers Feature Vector style
OpenLayers Layer Google v2
OpenLayers Format XML document
OpenLayers Geometry Curve
OpenLayers Format WFST v1
THREE RGBA_S3TC_DXT3_Format
THREE ReverseSubtractEquation
THREE ArrowHelper prototype setLength
THREE Path prototype absellipse
THREE ShaderChunk envmap_vertex
THREE CurvePath prototype closePath
THREE Camera prototype lookAt
THREE LuminanceAlphaFormat
THREE MeshLambertMaterial
THREE PerspectiveCamera prototype setViewOffset
THREE Skeleton prototype pose
THREE ShaderChunk morphnormal_vertex
THREE ShaderChunk envmap_pars_vertex
THREE NearestMipMapNearestFilter
THREE Path prototype bezierCurveTo
THREE Curve prototype getUtoTmapping
THREE CurvePath prototype getCurveLengths
THREE ShaderChunk color_fragment
THREE ShaderChunk defaultnormal_vertex
THREE RGBA_S3TC_DXT1_Format
THREE ShaderChunk color_vertex
THREE ShaderChunk envmap_pars_fragment
THREE Bone prototype updateMatrixWorld
THREE CurvePath prototype getBoundingBox
THREE DefaultLoadingManager
THREE OneMinusSrcColorFactor
THREE ShaderChunk morphtarget_vertex
THREE IcosahedronGeometry
THREE SubtractiveBlending
THREE ShaderChunk logdepthbuf_pars_fragment
THREE Animation prototype stop
THREE Path prototype quadraticCurveTo
THREE ShaderChunk specularmap_pars_fragment
THREE ShaderChunk map_fragment
THREE ShaderChunk alphamap_pars_fragment
THREE Curve prototype getTangentAt
THREE ShaderChunk morphtarget_pars_vertex
THREE ShaderChunk skinbase_vertex
THREE ShaderChunk logdepthbuf_fragment
THREE LinearMipMapLinearFilter
THREE Triangle containsPoint
THREE OneMinusDstAlphaFactor
THREE Curve prototype getLengths
THREE Curve prototype getPointAt
THREE Mesh prototype updateMorphTargets
THREE ShaderChunk lightmap_fragment
THREE RGB_S3TC_DXT1_Format
THREE Camera prototype clone
THREE ShaderChunk lights_phong_pars_fragment
THREE QuadraticBezierCurve3
THREE ShaderChunk skinnormal_vertex
THREE ShaderChunk lightmap_pars_fragment
THREE DirectionalLightHelper prototype dispose
THREE ShaderChunk map_particle_pars_fragment
THREE UnsignedShort5551Type
THREE ShaderChunk color_pars_fragment
THREE PointCloud prototype raycast
THREE ShaderChunk skinning_pars_vertex
THREE ClampToEdgeWrapping
THREE ShaderChunk fog_pars_fragment
THREE Curve prototype getLength
THREE LinearMipMapNearestFilter
THREE Path prototype absarc
THREE ShaderChunk normalmap_pars_fragment
THREE ShaderChunk color_pars_vertex
THREE Curve prototype getPoint
THREE ShaderChunk alphatest_fragment
THREE ExtrudeGeometry prototype addShape
THREE ShaderChunk bumpmap_pars_fragment
THREE SkinnedMesh prototype bind
THREE ShaderChunk envmap_fragment
THREE NearestMipMapLinearFilter
THREE Sprite prototype updateMatrix
THREE ShaderChunk logdepthbuf_vertex
THREE Path prototype ellipse
THREE TetrahedronGeometry
THREE OrthographicCamera prototype updateProjectionMatrix
THREE ShaderChunk map_pars_fragment
THREE ShaderChunk worldpos_vertex
THREE Curve prototype getPoints
THREE ShaderChunk specularmap_fragment
THREE OneMinusDstColorFactor
THREE Path prototype splineThru
THREE Shape prototype getPointsHoles
THREE LOD prototype getObjectForDistance
THREE Path prototype lineTo
THREE ShaderChunk shadowmap_pars_fragment
THREE ShaderChunk alphamap_fragment
THREE JSONLoader prototype parse
THREE LOD prototype addLevel
THREE SkinnedMesh prototype normalizeSkinWeights
THREE Shape prototype extractPoints
THREE ShaderChunk fog_fragment
THREE SrcAlphaSaturateFactor
THREE ShaderChunk default_vertex
THREE Animation prototype reset
THREE ShaderChunk shadowmap_pars_vertex
THREE MirroredRepeatWrapping
THREE Curve prototype getSpacedPoints
THREE Curve prototype updateArcLengths
THREE UnsignedShort4444Type
THREE Curve prototype getTangent
THREE ShaderChunk map_particle_fragment
THREE RGBA_S3TC_DXT5_Format
THREE Path prototype moveTo
THREE ShaderChunk lights_phong_fragment
THREE ExtrudeGeometry WorldUVGenerator
THREE CubeReflectionMapping
THREE CubeRefractionMapping
THREE ShaderChunk logdepthbuf_pars_vertex
THREE ShaderChunk shadowmap_vertex
THREE OneMinusSrcAlphaFactor
THREE CurvePath prototype add
THREE QuadraticBezierCurve
THREE JSONLoader prototype load
THREE Skeleton prototype update
THREE RenderableVertex prototype copy
THREE ShaderChunk skinning_vertex
THREE Skeleton prototype calculateInverses